27 Commits
Author SHA1 Message Date
pancake a215967e38 Import version 0.3 from tarball 0xFFFF-0.3.tar.gz 2007-10-20 02:32:24 +02:00
pancake fbdac811fc * Make the fiasco writing api work (some hardcoded things, but mostly ok)
* Move documentation of fiasco format to doc/
* 0.3 release
2007-10-20 02:32:24 +02:00
pancake d15412a788 * Add documentation for the FIASCO format
* Initial fiasco writer api
* Lot of new checks and code cleanup
* fiasco callback now receives a filedescriptor inside header_t
  - the lseek and data free is autonatically done by the main loop
* Split fiasco_data_read() code, useful for streams (embeddeds low mem footprint)
* Add '-P' flag to create a new fiasco pack
2007-10-11 03:14:11 +02:00
pancake 85fdbfb354 * Finally implement the support for the FIASCO firmware format
* Up version to 0.3
* Alphabetically order the help message flags
* Cleaner short help message
* Pseudo-api for creating firmwares (not yet finished)
* Add '-F' flag to flash from a fiasco image
2007-10-08 00:25:56 +02:00
pancake 11e32133b0 * Upgrade to GPLv3 2007-06-30 03:58:18 +02:00
pancake 1f3c790d87 * Initial import of the maemo bug report #1584 into documentation 2007-06-25 23:00:29 +02:00
pancake 6521a8e9d1 * Update documentation for the 0.2 release
* Fix case0 bug of libusb in usb_device_found function
2007-06-25 15:14:14 +02:00
pancake 3728cdea31 * Add new command 'nanddump' for the console shell
* Avoid dumping non-mtd files because writesize = 0
  - Properly close the file when failing

* Better doc/pieces documentation
2007-06-16 05:52:46 +02:00
pancake c1d909c415 * Fix the dump of xloader and secondary.bin
- Looks like they protect these blocks by marking this section as badblocks.
  - We just ignore badblock marks when dumping the bootloader

* Handle feof (^D) on the prompt
2007-06-16 05:21:14 +02:00
pancake 579dbe9837 * Fix device identification for n800. patch from Robert Schuster
- Looks like n770 and n800 have different USB identifiers on the
    bootloader and the operating system.

* Print oops message and exit when the use has no permissions to
  access to the usb.
2007-06-14 23:32:52 +02:00
pancake ed3cb1d3f8 * Finally integrate libusb in Makefiles. Use 'allusb' target to build a 0xFFFF binary without library dependencies (libusb)
* Add 'static' makefile target for building a statically linked 0xFFFF

* Documentate all makefile targets in INSTALL
2007-06-12 23:43:35 +02:00
pancake ea97ac427e * Initial import of the libusb source tree into the flasher - optional, but useful for embedding - avoids gnu autosux problems 2007-06-12 15:29:07 +02:00
pancake a3af55acb4 * Initial implementation of the pretty-print config partition dumper
* Handled with the '-x' flag.
2007-06-11 02:29:11 +02:00
pancake 83b41f9371 * Initial implementation of the "badblocks" (-C) command.
* Initial work on the reorganization of the dump.c code
  to avoid spagetti code. ATM is just a draft

* Dump now shows you more info
2007-06-10 16:15:30 +02:00
pancake c46961d511 * Fix in fpid for proper JFFS2 identification
* Add new flag '-c' that makes 0xFFFF run as a shell
* Split the connect_via_usb() code from main()
* Add console handler for shell like usage of the flasher
2007-06-10 05:41:50 +02:00
pancake ec71146727 * Drop the partition limit. It is calculed with ioctl()
* Query the user to strip or not the dumped pieces
* Add new flag '-s' for serial port console
2007-06-10 00:38:55 +02:00
pancake 43d8d45919 * Initial import of the offline work of the GUI environment
- Not yet usable, it's just a sketch with glade O:)
- But you can get fun hacking on the source!

* Add deinstall target to the Makefile

* Add INSTALL file for build & install instructions

* Add documentation for local flashing.
2007-06-02 05:32:43 +02:00
pancake f299486ef9 * Covardly copy the nanddump() function from the mtd-utils to fix dump functionality
- The new function works like the old rf_extract one, no parameters has
  changed.
- Now a complete dump/restore will be possible.
- Check for badblocks while copying data
- Shows information about the partition

* Better use of query_error_message() for debugging
2007-06-02 02:23:58 +02:00
pancake 1515b7c7c1 * Fix rootfs boundaries for a proper dump.
* Replace Y/n for y/N
* Implement the command '5' (read error message)
2007-05-25 00:33:58 +02:00
pancake ed37b5ee62 * Enhacements and fixups for logotool
* Add support for RGBA raw images (New flag -a)
* Autodetect RGBA images
* Fix endianness stuff when writting the logo header
2007-05-05 03:04:52 +02:00
pancake d0f9d78335 * Move usb-dev related code to devices.c from main.c
* Create a root Makefile to build the flasher, logotool and install
* Clean some warning messages
2007-05-01 15:01:23 +02:00
pancake 3e13254858 * Initial import of the logotool utility 2007-04-30 06:26:27 +02:00
pancake 5e3de1ba06 * Argument 'help' for the -f flag provides information about the rd flags 2007-04-26 00:30:46 +02:00
pancake 5b5425e0d0 * import of the 'set-rd-flags+cleanups' patch from Robert Schuster
adds support for setting and clearing the rd flags (no-retu-watchdog,
  serial-console and the like).

  The interface to it is a bit cryptic (construct your own hex number) but
  it works like like 'chmod'.
2007-04-25 21:47:53 +02:00
pancake 60f2337927 * import of the 'set-get-query_header' from Robert Schuster
1) name the simple functions get_foo and set_foo (and make them more
  consistent e.g. set_rd_mode and get_rd_mode).

  2) moved remaining simple queries from main.c into query.c

  3) created separate query.h header and included it in main.c

  4) implemented get_usb_mode (they do not have this in the proprietary
  flasher) and added this function to a normal run (-> you will see the
  current USB mode when running with -i)
2007-04-25 21:05:03 +02:00
pancake 196f1f7abb * Do not strip the initfs.jffs2 image, it is only 2MB
* Some fixups on the doc/dumping documentation
2007-04-20 21:00:12 +02:00
pancake 300635ad8f * 'set root device' patch inclusion from Robert Schuster 2007-04-20 18:27:31 +02:00
57 changed files with 9080 additions and 776 deletions

No files matched your search

+753 -251
View File
File diff suppressed because it is too large. Load diff
+29
View File
@@ -0,0 +1,29 @@
Installation instructions:
==========================
To build the flasher you will need gcc, make and libusb. For crosscompiling
to arm you can use scratchbox. But you will probably need the libusb.so of
the scratchbox environment to the device.
Just type:
$ make
The most interesting targets for make are:
all normal build
allusb builds 0xFFFF without libusb dependency (embedded)
static builds 0xFFFF statically (no need for libusb)
install installs into /usr/local by default
clean clean compilation objects and generated binaries
The installation procedure is quite simple and you can define a new PREFIX
manually from the command line:
$ sudo make install PREFIX=/usr
The default one is /usr/local (not very userfriendly but standards are
standards :P hehe)
+27
View File
@@ -0,0 +1,27 @@
PREFIX?=/usr/local
all: logot
cd src && ${MAKE} all
static: logot
cd libusb && ${MAKE} all
cd src && ${MAKE} static
allusb: logot
cd libusb && ${MAKE} all
cd src && ${MAKE} allusb
logot:
cd logotool && ${MAKE} all
clean:
cd src && ${MAKE} clean
cd logotool && ${MAKE} clean
install:
cp src/0xFFFF ${PREFIX}/bin
cp logotool/logotool ${PREFIX}/bin
deinstall:
rm -f ${PREFIX}/bin/0xFFFF
rm -f ${PREFIX}/bin/logotool
+9 -6
View File
@@ -1,6 +1,5 @@
------. ,---------.--.--.
/ | ___ | | | \\------------ -- .
| .__ / \/ . ____/ _/ _/ The 0pen
@@ -11,19 +10,23 @@
_/ ___|_.|__|
'`
The 'Free Fiasco Firmware Flasher' aka 0xFFFF utility tries to implement
a free (GPL'd) userspace handler for the NOLO bootloader.
The 'Free Fiasco Firmware Flasher' aka 0xFFFF utility implements a free
(under the GPLv3 license) userspace handler for the NOLO bootloader and
extended features for flashing, dumping and getting information for the
Nokia Internet Tablets.
Use it with CARE. This is an experimental tool and it can brick your device.
It's not suposed to be stable, so nokia will probably release incompatible
bootloaders to break this tool. USE IT AT YOUR OWN RISK.
This tool has been designed and tested on n770. The n800 flash should work
but it's not tested and is known to use different request codes.
PLEASE. Read carefully all the documentation inside doc/* for more information
before building or using the flasher to avoid questions, problems or so.
Feel free to join to the mailing list and visit the homepage for more info:
0xffff@lists.nopcode.org
http://www.nopcode.org/0xFFFF
Have phun!
+60
View File
@@ -0,0 +1,60 @@
Bug#: 1584
Opened: 2007-06-25 23:06 GMT+3
Reporter: Robert Schuster <thebohemian [at] gmx.net>
Summary: provide system management software under free software licenses
Several applications and libraries found on the N800 internet tablet/IT OS
2007.10 are distributed under restricted and non-free license terms according
to the Debian Free Software Guidelines, Open Source Definition and Free
Software definition.
I hereby politely ask for distributing those components under terms that are
acceptable to the above mentioned guidelines.
The applications of interest are:
from the initfs: activate_panel, bt-cal, cal-tool, fb-chaimage, text2screen,
wlan-cal, wlan-fw-update, retu-time, show_image, dsme, battest, bootstate,
dsmetool, dspctl, waitfordsme and the script linuxrc
the libraries of interest are:
libbmeic.so, libcal.so, libdsme.so, libppu.so, libactivitymonitor.so,
libcalmodule.so, libhwwd.so, libinactivity-blank.so, liblifeguard.so,
libperipheral.so, libprocesswd.so, libstartup.so, libstate.so,
libtemperature.so
There may be other software artifacts which are of interest for which I will
file separate bugreports if there is a need for them.
Rationale:
When Nokia/Maemo decided to use a variant of the GNU operating system and Linux
as its kernel for implementing the Internet Tablet OS they profited from a
wealth of knowledge and work invested in various software projects. With the
help of free software licensing they were allowed to create a unique software
environment which exactly implements the Maemo projects' goals. Maemo has
gained and still gains from those software projects because they are
independently developed further giving Maemo more possibilities in the future.
One of the key goals of the GNU project is to give its user's the freedom to
implement their own ideas. This goal is to be reached by writing free software
and sometimes (in the early days often) replacing proprietary software.
The non-free bits in the core infrastructure of the IT OS 2007 are a road block
for efforts to create free operating systems/distributions besides IT OS on the
N770/N800.
The reason for why it is helpful to have other operating system/distribution on
the N800 is simple: There are hundreds of GNU/Linux distributions out there.
Each one exists because there is a userbase that exactly likes their flavor of
GNU/Linux.
For the N770/N800 Internet Tablets there exists only one such distribution: The
Internet Tablet OS. With the sheer amount of GNU/Linux distributions for
desktops/workstations/servers/routers/PDAs on the one hand and the single OS
solution for the Internet Tablets on the other I doubt that it can handle all
the possible uses people have.
By releasing the above mentioned programs/libraries under free software
licenses people will be given the same possibilities the Maemo project had in
the first place.
Let us be free.
+34 -22
View File
@@ -3,30 +3,12 @@
This technique consists on reconstructing a firmware image dumping
pieces at certains offsets of the device internal memory.
<b>End user details:</b>
* Extract the firmware pieces from a running device
*
* This functionality is useful to extract backups of your system
* firmware. This is really useful when you're on a desert island
* without an internet connection.
*
* This tool needs more testing, so take care and don't blame me if
* it breaks your system. It *is* to your responsability, use at
* your own risk
*
* NOTE: It's theorically possible to flash the device on the fly from
* the running OS, but this has not yet been tested. Keep tuned for
* updates and newz.
*
* Have fun!
<b></b>
<b>Technical details:</b>
* The internal flash memory is exposed to the system as MTD devices. So it's
* possible to dump the individual sections of a flashed firmware.
* The internal flash memory is exposed to the system as MTD devices.
* Is possible to dump the individual sections of a flashed firmware.
*
* READ src/dump.c for detailed information.
@@ -40,6 +22,36 @@ pieces at certains offsets of the device internal memory.
mtd2 - starts with NOLO img\x5c\x13 and \x00 padding
0x00800 - zImage
mtd3 - rootfs.jffs2 (20M) aka 0x200000 vs 0x3900000
> NOLO is a four byte marker, next four bytes
> can vary since it is kernel image size
mtd3 - initfs.jffs2 (2M) aka 0x200000 vs 0x3900000
mtd4 - rootfs.jffs2 (a fucking copy of the above rootfs?)
// Extra notes //
[MTD] NAND Consolidate oobinfo handling
The info structure for out of band data was copied into
the mtd structure. Make it a pointer and remove the ability
to set it from userspace. The position of ecc bytes is
defined by the hardware and should not be changed by software.
// The oob stuff
In mtd3 the OOB data is 64 bytes aka 0x40, and this oob stuff
appears every 2KB aka 0x800 bytes.
/*
* Obsolete legacy interface. Keep it in order not to break userspace
* interfaces
*/
struct nand_oobinfo {
uint32_t useecc;
uint32_t eccbytes;
uint32_t oobfree[8][2];
uint32_t eccpos[32];
};
+9
View File
@@ -68,3 +68,12 @@ This file tries to collect a bunch of common questions/answers about flashing
information of different pieces of the firmware. This can be faked, because
you can flash n770 stuff on n800 and viceversa, but it's not recommended
because it wouldn't work :)
<b>*) Can I unpack fiasco blobs?</b>
Actually the fiasco format is not yet supported and not planned in
short term. There is no real need for supporting a proprietary
format image containing a proprietary system.
We can just use tarballs containing the desired pieces.
+30
View File
@@ -0,0 +1,30 @@
SPECS FOR TEH FIASCO FIRMWARE FILE FORMAT ffff!
-----------------------------------------------
These notes has not been taken properly and may be wrong. It must
be revised to fit the reality. But this is mostly a general idea:
FILE HEADER
1 byte = 0xb4 -- signature
4 bytes -- firmware name length (big endian)
6 bytes -- versioning info ( byte 4 is format version )
N-6 bytes -- firmware name (zero fill)
PIECE HEADER
1 byte = 0x54 -- piece signature
6 bytes -- unknown
2 bytes -- checksum for the piece contents (xorpair)
12 bytes -- piece name (first byte is FF if is the last)
4 bytes -- piece size (big endian)
4 bytes -- unknown
block {
1 byte -- if (value '1'-'9') { ..there's a comment.. }
1 byte -- length of comment
N bytes -- comment
}
N bytes -- piece data
+24
View File
@@ -0,0 +1,24 @@
It is possible to flash directly from the device, so this brings the possibility
to completely replace the bootloader flasher by a userland one with extended
features for backuping and recovering data.
The way to flash is using mtd-utils:
$ flash_eraseall -j /dev/mtd3
$ nandwrite -a -p /dev/mtd3 initfs.jffs2
This is an specific example plagied from initfs_flasher of bootmenu.
The '-j' flag says that this is a jffs2 partition. Theorically this
flag is not required for zImage, and the bootloader pieces.
The '-a' creates the OOB data automatically, and the '-p' flag pads
the data to fill the block.
These flags are only fine for initfs, so this will be probably wrong
for other pieces. Using the dump functionality you can check if you
have flashed properly every piece inside the device, but keep in mind
that it is dangerous and you can brick your device.
But feel free to send feedback to provide a full support for local
flashing on n770 and n800.
-2
View File
@@ -1,2 +0,0 @@
Consequences of a weird flashing :)<br />
<img src="img/n770bars.jpg">
+37
View File
@@ -4,3 +4,40 @@ Fiasco firmware pieces
The firmware for the maemo devices is composed by a set of pieces containing
the required parts to update the whole system following a partition layout
defined by NOLO on the internal flash memory.
Nokia provides a blob packed with a proprietary format called 'FIASCO'. This
blob contains the following pieces:
- omap-nand - only flashable via serial jtag
- xloader - first part of nolo
- secondary - second part of nolo (usb support and launches kernel)
- kernel - the kernel
- initfs - initial system that initializes everything and runs rootfs
- rootfs - the whole system image
Some of these pieces are versioned to match board specific features
(mostly xloader and secondary ones).
This format is not supported by 0xFFFF at this moment, but there are no
plans for doing it in short term. This is because we only need to flash
separated pieces. We can just distribute tarballs containing the pieces
and meta information with a whole Free OS for the internet tablets.
To flash an initfs partition and reboot:
$ 0xFFFF -p initfs%initfs.jffs2 -R
The format of the argument is [piece-type] % [file-name] (% [version-string]).
Pieces can be automatically identified by using the '-I' flag:
$ 0xFFFF -I initfs.jffs2
initfs.jffs2: initfs
You can dump these pieces from the internal memory of the internet
tablet by using the mtd-utils over /dev/mtd* or just running:
n770$ 0xFFFF -e /media/mmc1
There is another way for dumping pieces with extra parameters and options,
read doc/dumping for more information.
+30 -16
View File
@@ -8,27 +8,41 @@ Tablets (n770 and n800).
- reboot de mother board
- extract the current firmware pieces from the device (dump)
- set the USB host/slave mode
- set the R&R mode
- pack/unpack fiasco firmwares
- fine grained R&D flags support
- identify firmware pieces
- dump mtd partitions (embedded mtd-utils source code)
- reconstruct initfs from a dump
- dump config partition
- automatic piece identifier
- console mode (shell like)
</pre>
This is the help message of the tool:
<pre>
<b>~$ 0xFFFF -h</b>
0xFFFF v0.1 - The Open Free Fiasco Firmware Flasher
-b [arg] boots the kernel with arguments
-e [path] dump the firmware pieces into the path
-p [[p:]file] piece-of-firmware : file-where-this-piece-is
-r [0|1] disable/enable R&D mode
-u [fiasco] unpack target fiasco image
-U [0|1] disable/enable the usb host mode
-h show this help message
-i show device information (let standby mode)
-I [piece] identify a firmware piece
-l list supported usb device ids
-d [vid:pid] injects a usb device into the supported list
-R reboot the omap board
-v be verbose and noisy
-V show 0xFFFF version information
0xFFFF v0.3 // The Free Fiasco Firmware Flasher
-b [arg] boots the kernel with arguments
-c console prompt mode
-C [/dev/mtd] check bad blocks on mtd
-d [vid:pid] injects a usb device into the supported list
-D [0|1|2] sets the root device to flash (0), mmc (1) or usb (2)
-e [path] dump and extract pieces to path
-f <flags> set the given RD flags (see '-f help')
-F [fiasco] flash a fiasco firmware image
-h show this help message
-H [file] calculate hash for file
-i show device information (let standby mode)
-I [piece] identify a firmware piece
-l, -L list supported usb device ids
-p [[p%]file] piece-of-firmware % file-where-this-piece-is
-r [0|1] disable/enable R&D mode
-R reboot the omap board
-s [serial] serial port console (minicom like terminal)
-u [fiasco] unpack target fiasco image
-U [0|1] disable/enable the usb host mode
-v be verbose and noisy
-V show 0xFFFF version information
-x extract configuration entries from /dev/mtd1
Pieces are: xloader secondary kernel initfs rootfs omap-nand
</pre>
+53
View File
@@ -0,0 +1,53 @@
- preferences
* choose flasher type.
by default 0xFFFF is used
*
piece [file]
|
+-- radio
|
+-- nbh
info
|
+-- -i
reboot
|
+-- ???
----------
piece [file]
|
+-- xloader
|
+-- secondary
|
+-- kernel
|
+-- initfs
|
+-- rootfs
|
+-- autodetected
info
|
+-- -i
usb-host-mode
|
+-- -U [0|1]
rd-mode
|
+-- -r 0|1
reboot
|
+-- -R
+8
View File
@@ -0,0 +1,8 @@
OBJ=main.o
BIN=goxf
CFLAGS=`pkg-config libgladeui-1.0 libglade-2.0 --cflags`
LDFLAGS=`pkg-config libgladeui-1.0 libglade-2.0 --libs`
all: ${OBJ}
${CC} ${LDFLAGS} ${OBJ} -o ${BIN}
+223
View File
@@ -0,0 +1,223 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkWindow" id="main_window">
<property name="border_width">5</property>
<property name="title" translatable="yes" context="yes">g0xFFFF</property>
<property name="default_width">501</property>
<property name="default_height">329</property>
<property name="icon_name">gtk-connect</property>
<signal name="destroy_event" handler="gtk_main_quit" object="0"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox2">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_START</property>
<child>
<widget class="GtkComboBox" id="combobox2">
<property name="visible">True</property>
<property name="active">0</property>
<property name="items" translatable="yes" context="yes">n770/n800
HERMflasher</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="gochange">
<property name="width_request">32</property>
<property name="visible">True</property>
<property name="has_default">True</property>
<property name="label" translatable="yes" context="yes">&gt;</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<widget class="GtkTreeView" id="treeview1">
<property name="visible">True</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="border_width">3</property>
<property name="spacing">2</property>
<child>
<widget class="GtkFileChooserButton" id="filechooserbutton2">
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="combo1">
<property name="row_span_column">0</property>
<property name="column_span_column">0</property>
<property name="active">0</property>
<property name="tearoff_title">patata</property>
<property name="items" translatable="yes" context="yes">rootfs
initfs
kernel
secondary
xloader</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<child>
<widget class="GtkButton" id="button2">
<property name="visible">True</property>
<property name="label" context="yes">Remove</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="add">
<property name="visible">True</property>
<property name="label" context="yes">Add</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="checkbutton2">
<property name="visible">True</property>
<property name="label" translatable="yes" context="yes">USB host mode</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="checkbutton3">
<property name="visible">True</property>
<property name="label" translatable="yes" context="yes">R&amp;D mode</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="reboot">
<property name="visible">True</property>
<property name="label" translatable="yes" context="yes">Reboot</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">3</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkProgressBar" id="progressbar1">
<property name="visible">True</property>
<property name="show_text">True</property>
</widget>
</child>
<child>
<widget class="GtkHBox" id="hbox5">
<property name="visible">True</property>
<child>
<widget class="GtkButton" id="info">
<property name="visible">True</property>
<property name="label" translatable="yes" context="yes">gtk-dialog-info</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="but_commit">
<property name="visible">True</property>
<property name="label" translatable="yes" context="yes">gtk-execute</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">GTK_PACK_END</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
+49
View File
@@ -0,0 +1,49 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <glade/glade.h>
#include <gtk/gtk.h>
#define U(x) printf("%d\n",x); fflush(stdout);
int main(int argc, char **argv)
{
GtkWidget *w;
GladeXML *xml;
gtk_init(&argc, &argv);
xml = glade_xml_new("g0xFFFF.glade", "main_window", "");
//xml = glade_xml_new("test.glade", "window1", NULL);
if(!xml) {
g_warning("We could not load the interface!");
return 1;
}
glade_xml_signal_autoconnect(xml);
w = glade_xml_get_widget(xml, "main_window");
gtk_signal_connect(GTK_OBJECT(w), "destroy",
GTK_SIGNAL_FUNC(gtk_main_quit),NULL);
gtk_widget_show_all(w);
gtk_object_unref(GTK_OBJECT(xml));
gtk_main();
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
#include ../config.mk
OBJ=linux.o usb.o descriptors.o error.o
all: ${OBJ}
${CC} ${CFLAGS} ${LDFLAGS} -fPIC -I . ${OBJ} -shared -o libusb.so
clean:
-rm -f libusb.so ${OBJ}
+637
View File
@@ -0,0 +1,637 @@
/*
* (Free|Open|Net)BSD USB support
*
* Derived from Linux version by Richard Tobin.
*
* $Id: bsd.c,v 1.33 2006/03/04 01:16:10 jerdfelt Exp $
* $Name: $
*
* This library is covered by the LGPL, read LICENSE for details.
*/
/*
* Note: I don't have a clue what I'm doing. I just looked at the
* man pages and source to try and find things that did the same as
* the Linux version. -- Richard
*
* johnjen@reynoldsnet.org - minor fixes with debug mode output. Consistent brace
* use as well as indenting. More error messages put in to test for failure
* modes with /dev/ permissions (when it happens). Note: I, like Richard, have
* no clue what I'm doing. Patches to increase/fix functionality happily
* accepted!
*/
/* dirkx@webweaving.org - minor changes to make things actually work
* for both read and write.
*/
#if defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
#define __FreeBSD_kernel__ __FreeBSD__
#endif
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <dev/usb/usb.h>
#include "usbi.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_OLD_DEV_USB_USB_H
/*
* It appears some of the BSD's (OpenBSD atleast) have switched over to a
* new naming convention, so we setup some macro's for backward
* compability with older versions --jerdfelt
*/
/* struct usb_ctl_request */
#define ucr_addr addr
#define ucr_request request
#define ucr_data data
#define ucr_flags flags
#define ucr_actlen actlen
/* struct usb_alt_interface */
#define uai_config_index config_index
#define uai_interface_index interface_index
#define uai_alt_no alt_no
/* struct usb_config_desc */
#define ucd_config_index config_index
#define ucd_desc desc
/* struct usb_interface_desc */
#define uid_config_index config_index
#define uid_interface_index interface_index
#define uid_alt_index alt_index
#define uid_desc desc
/* struct usb_endpoint_desc */
#define ued_config_index config_index
#define ued_interface_index interface_index
#define ued_alt_index alt_index
#define ued_endpoint_index endpoint_index
#define ued_desc desc
/* struct usb_full_desc */
#define ufd_config_index config_index
#define ufd_size size
#define ufd_data data
/* struct usb_string_desc */
#define usd_string_index string_index
#define usd_language_id language_id
#define usd_desc desc
/* struct usb_ctl_report_desc */
#define ucrd_size size
#define ucrd_data data
/* struct usb_device_info */
#define udi_bus bus
#define udi_addr addr
#define udi_cookie cookie
#define udi_product product
#define udi_vendor vendor
#define udi_release release
#define udi_productNo productNo
#define udi_vendorNo vendorNo
#define udi_releaseNo releaseNo
#define udi_class class
#define udi_subclass subclass
#define udi_protocol protocol
#define udi_config config
#define udi_lowspeed lowspeed
#define udi_power power
#define udi_nports nports
#define udi_devnames devnames
#define udi_ports ports
/* struct usb_ctl_report */
#define ucr_report report
#define ucr_data data
/* struct usb_device_stats */
#define uds_requests requests
#endif
static int ensure_ep_open(usb_dev_handle *dev, int ep, int mode);
#define MAX_CONTROLLERS 10
/* This records the file descriptors for the endpoints. It doesn't seem
to work to re-open them for each read (as well as being inefficient). */
struct bsd_usb_dev_handle_info {
int ep_fd[USB_MAX_ENDPOINTS];
};
int usb_os_open(usb_dev_handle *dev)
{
int i;
struct bsd_usb_dev_handle_info *info;
char ctlpath[PATH_MAX + 1];
info = malloc(sizeof(struct bsd_usb_dev_handle_info));
if (!info)
USB_ERROR(-ENOMEM);
dev->impl_info = info;
#ifdef __FreeBSD_kernel__
snprintf(ctlpath, PATH_MAX, "%s", dev->device->filename);
#else
snprintf(ctlpath, PATH_MAX, "%s.00", dev->device->filename);
#endif
dev->fd = open(ctlpath, O_RDWR);
if (dev->fd < 0) {
dev->fd = open(ctlpath, O_RDONLY);
if (dev->fd < 0) {
free(info);
USB_ERROR_STR(-errno, "failed to open %s: %s",
ctlpath, strerror(errno));
}
}
/* Mark the endpoints as not yet open */
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
info->ep_fd[i] = -1;
return 0;
}
int usb_os_close(usb_dev_handle *dev)
{
struct bsd_usb_dev_handle_info *info = dev->impl_info;
int i;
/* Close any open endpoints */
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
if (info->ep_fd[i] >= 0) {
if (usb_debug >= 2)
fprintf(stderr, "usb_os_close: closing endpoint %d\n", info->ep_fd[i]);
close(info->ep_fd[i]);
}
free(info);
if (dev->fd <= 0)
return 0;
if (close(dev->fd) == -1)
/* Failing trying to close a file really isn't an error, so return 0 */
USB_ERROR_STR(0, "tried to close device fd %d: %s", dev->fd,
strerror(errno));
return 0;
}
int usb_set_configuration(usb_dev_handle *dev, int configuration)
{
int ret;
ret = ioctl(dev->fd, USB_SET_CONFIG, &configuration);
if (ret < 0)
USB_ERROR_STR(-errno, "could not set config %d: %s", configuration,
strerror(errno));
dev->config = configuration;
return 0;
}
int usb_claim_interface(usb_dev_handle *dev, int interface)
{
/* BSD doesn't have the corresponding ioctl. It seems to
be sufficient to open the relevant endpoints as needed. */
dev->interface = interface;
return 0;
}
int usb_release_interface(usb_dev_handle *dev, int interface)
{
/* See above */
return 0;
}
int usb_set_altinterface(usb_dev_handle *dev, int alternate)
{
int ret;
struct usb_alt_interface intf;
if (dev->interface < 0)
USB_ERROR(-EINVAL);
intf.uai_interface_index = dev->interface;
intf.uai_alt_no = alternate;
ret = ioctl(dev->fd, USB_SET_ALTINTERFACE, &intf);
if (ret < 0)
USB_ERROR_STR(-errno, "could not set alt intf %d/%d: %s",
dev->interface, alternate, strerror(errno));
dev->altsetting = alternate;
return 0;
}
static int ensure_ep_open(usb_dev_handle *dev, int ep, int mode)
{
struct bsd_usb_dev_handle_info *info = dev->impl_info;
int fd;
char buf[20];
/* Get the address for this endpoint; we could check
* the mode against the direction; but we've done that
* already in the usb_bulk_read/write.
*/
ep = UE_GET_ADDR(ep);
if (info->ep_fd[ep] < 0) {
#ifdef __FreeBSD_kernel__
snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->device->filename, ep);
#else
snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->device->filename, ep);
#endif
/* Try to open it O_RDWR first for those devices which have in and out
* endpoints with the same address (eg 0x02 and 0x82)
*/
fd = open(buf, O_RDWR);
if (fd < 0 && errno == ENXIO)
fd = open(buf, mode);
if (fd < 0)
USB_ERROR_STR(-errno, "can't open %s for bulk read: %s",
buf, strerror(errno));
info->ep_fd[ep] = fd;
}
return info->ep_fd[ep];
}
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
int fd, ret;
/* Ensure the endpoint address is correct */
ep &= ~USB_ENDPOINT_IN;
fd = ensure_ep_open(dev, ep, O_WRONLY);
if (fd < 0) {
if (usb_debug >= 2) {
#ifdef __FreeBSD_kernel__
fprintf (stderr, "usb_bulk_write: got negative open file descriptor for endpoint %d\n", UE_GET_ADDR(ep));
#else
fprintf (stderr, "usb_bulk_write: got negative open file descriptor for endpoint %02d\n", UE_GET_ADDR(ep));
#endif
}
return fd;
}
ret = ioctl(fd, USB_SET_TIMEOUT, &timeout);
if (ret < 0)
USB_ERROR_STR(-errno, "error setting timeout: %s",
strerror(errno));
ret = write(fd, bytes, size);
if (ret < 0)
#ifdef __FreeBSD_kernel__
USB_ERROR_STR(-errno, "error writing to bulk endpoint %s.%d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#else
USB_ERROR_STR(-errno, "error writing to bulk endpoint %s.%02d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#endif
return size;
}
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
int fd, ret, one = 1;
/* Ensure the endpoint address is correct */
ep |= USB_ENDPOINT_IN;
fd = ensure_ep_open(dev, ep, O_RDONLY);
if (fd < 0) {
if (usb_debug >= 2) {
#ifdef __FreeBSD_kernel__
fprintf (stderr, "usb_bulk_read: got negative open file descriptor for endpoint %d\n", UE_GET_ADDR(ep));
#else
fprintf (stderr, "usb_bulk_read: got negative open file descriptor for endpoint %02d\n", UE_GET_ADDR(ep));
#endif
}
return fd;
}
ret = ioctl(fd, USB_SET_TIMEOUT, &timeout);
if (ret < 0)
USB_ERROR_STR(-errno, "error setting timeout: %s", strerror(errno));
ret = ioctl(fd, USB_SET_SHORT_XFER, &one);
if (ret < 0)
USB_ERROR_STR(-errno, "error setting short xfer: %s", strerror(errno));
ret = read(fd, bytes, size);
if (ret < 0)
#ifdef __FreeBSD_kernel__
USB_ERROR_STR(-errno, "error reading from bulk endpoint %s.%d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#else
USB_ERROR_STR(-errno, "error reading from bulk endpoint %s.%02d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#endif
return ret;
}
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
int fd, ret, sent = 0;
/* Ensure the endpoint address is correct */
ep &= ~USB_ENDPOINT_IN;
fd = ensure_ep_open(dev, ep, O_WRONLY);
if (fd < 0) {
if (usb_debug >= 2) {
#ifdef __FreeBSD_kernel__
fprintf (stderr, "usb_interrupt_write: got negative open file descriptor for endpoint %d\n", UE_GET_ADDR(ep));
#else
fprintf (stderr, "usb_interrupt_write: got negative open file descriptor for endpoint %02d\n", UE_GET_ADDR(ep));
#endif
}
return fd;
}
ret = ioctl(fd, USB_SET_TIMEOUT, &timeout);
if (ret < 0)
USB_ERROR_STR(-errno, "error setting timeout: %s",
strerror(errno));
do {
ret = write(fd, bytes+sent, size-sent);
if (ret < 0)
#ifdef __FreeBSD_kernel__
USB_ERROR_STR(-errno, "error writing to interrupt endpoint %s.%d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#else
USB_ERROR_STR(-errno, "error writing to interrupt endpoint %s.%02d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#endif
sent += ret;
} while (ret > 0 && sent < size);
return sent;
}
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
int fd, ret, retrieved = 0, one = 1;
/* Ensure the endpoint address is correct */
ep |= USB_ENDPOINT_IN;
fd = ensure_ep_open(dev, ep, O_RDONLY);
if (fd < 0) {
if (usb_debug >= 2) {
#ifdef __FreeBSD_kernel__
fprintf (stderr, "usb_interrupt_read: got negative open file descriptor for endpoint %d\n", UE_GET_ADDR(ep));
#else
fprintf (stderr, "usb_interrupt_read: got negative open file descriptor for endpoint %02d\n", UE_GET_ADDR(ep));
#endif
}
return fd;
}
ret = ioctl(fd, USB_SET_TIMEOUT, &timeout);
if (ret < 0)
USB_ERROR_STR(-errno, "error setting timeout: %s", strerror(errno));
ret = ioctl(fd, USB_SET_SHORT_XFER, &one);
if (ret < 0)
USB_ERROR_STR(-errno, "error setting short xfer: %s", strerror(errno));
do {
ret = read(fd, bytes+retrieved, size-retrieved);
if (ret < 0)
#ifdef __FreeBSD_kernel__
USB_ERROR_STR(-errno, "error reading from interrupt endpoint %s.%d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#else
USB_ERROR_STR(-errno, "error reading from interrupt endpoint %s.%02d: %s",
dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
#endif
retrieved += ret;
} while (ret > 0 && retrieved < size);
return retrieved;
}
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
int value, int index, char *bytes, int size, int timeout)
{
struct usb_ctl_request req;
int ret;
if (usb_debug >= 3)
fprintf(stderr, "usb_control_msg: %d %d %d %d %p %d %d\n",
requesttype, request, value, index, bytes, size, timeout);
req.ucr_request.bmRequestType = requesttype;
req.ucr_request.bRequest = request;
USETW(req.ucr_request.wValue, value);
USETW(req.ucr_request.wIndex, index);
USETW(req.ucr_request.wLength, size);
req.ucr_data = bytes;
req.ucr_flags = USBD_SHORT_XFER_OK;
ret = ioctl(dev->fd, USB_SET_TIMEOUT, &timeout);
#if (__NetBSD__ || __OpenBSD__)
if (ret < 0 && errno != EINVAL)
#else
if (ret < 0)
#endif
USB_ERROR_STR(-errno, "error setting timeout: %s",
strerror(errno));
ret = ioctl(dev->fd, USB_DO_REQUEST, &req);
if (ret < 0)
USB_ERROR_STR(-errno, "error sending control message: %s",
strerror(errno));
return UGETW(req.ucr_request.wLength);
}
int usb_os_find_busses(struct usb_bus **busses)
{
struct usb_bus *fbus = NULL;
int controller;
int fd;
char buf[20];
for (controller = 0; controller < MAX_CONTROLLERS; controller++) {
struct usb_bus *bus;
snprintf(buf, sizeof(buf) - 1, "/dev/usb%d", controller);
fd = open(buf, O_RDWR);
if (fd < 0) {
if (usb_debug >= 2)
if (errno != ENXIO && errno != ENOENT)
fprintf(stderr, "usb_os_find_busses: can't open %s: %s\n",
buf, strerror(errno));
continue;
}
close(fd);
bus = malloc(sizeof(*bus));
if (!bus)
USB_ERROR(-ENOMEM);
memset((void *)bus, 0, sizeof(*bus));
strncpy(bus->dirname, buf, sizeof(bus->dirname) - 1);
bus->dirname[sizeof(bus->dirname) - 1] = 0;
LIST_ADD(fbus, bus);
if (usb_debug >= 2)
fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
}
*busses = fbus;
return 0;
}
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
{
struct usb_device *fdev = NULL;
int cfd, dfd;
int device;
cfd = open(bus->dirname, O_RDONLY);
if (cfd < 0)
USB_ERROR_STR(-errno, "couldn't open(%s): %s", bus->dirname,
strerror(errno));
for (device = 1; device < USB_MAX_DEVICES; device++) {
struct usb_device_info di;
struct usb_device *dev;
unsigned char device_desc[DEVICE_DESC_LENGTH];
char buf[20];
di.udi_addr = device;
if (ioctl(cfd, USB_DEVICEINFO, &di) < 0)
continue;
/* There's a device; is it one we should mess with? */
if (strncmp(di.udi_devnames[0], "ugen", 4) != 0)
/* best not to play with things we don't understand */
continue;
#ifdef __FreeBSD_kernel__
snprintf(buf, sizeof(buf) - 1, "/dev/%s", di.udi_devnames[0]);
#else
snprintf(buf, sizeof(buf) - 1, "/dev/%s.00", di.udi_devnames[0]);
#endif
/* Open its control endpoint */
dfd = open(buf, O_RDONLY);
if (dfd < 0) {
if (usb_debug >= 2)
fprintf(stderr, "usb_os_find_devices: couldn't open device %s: %s\n",
buf, strerror(errno));
continue;
}
dev = malloc(sizeof(*dev));
if (!dev)
USB_ERROR(-ENOMEM);
memset((void *)dev, 0, sizeof(*dev));
dev->bus = bus;
/* we need to report the device name as /dev/ugenx NOT /dev/ugenx.00
* This seemed easier than having 2 variables...
*/
#if (__NetBSD__ || __OpenBSD__)
snprintf(buf, sizeof(buf) - 1, "/dev/%s", di.udi_devnames[0]);
#endif
strncpy(dev->filename, buf, sizeof(dev->filename) - 1);
dev->filename[sizeof(dev->filename) - 1] = 0;
if (ioctl(dfd, USB_GET_DEVICE_DESC, device_desc) < 0)
USB_ERROR_STR(-errno, "couldn't get device descriptor for %s: %s",
buf, strerror(errno));
close(dfd);
usb_parse_descriptor(device_desc, "bbwbbbbwwwbbbb", &dev->descriptor);
LIST_ADD(fdev, dev);
if (usb_debug >= 2)
fprintf(stderr, "usb_os_find_devices: Found %s on %s\n",
dev->filename, bus->dirname);
}
close(cfd);
*devices = fdev;
return 0;
}
int usb_os_determine_children(struct usb_bus *bus)
{
/* Nothing yet */
return 0;
}
void usb_os_init(void)
{
/* nothing */
}
int usb_resetep(usb_dev_handle *dev, unsigned int ep)
{
/* Not yet done, because I haven't needed it. */
USB_ERROR_STR(-ENOSYS, "usb_resetep called, unimplemented on BSD");
}
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
{
/* Not yet done, because I haven't needed it. */
USB_ERROR_STR(-ENOSYS, "usb_clear_halt called, unimplemented on BSD");
}
int usb_reset(usb_dev_handle *dev)
{
/* Not yet done, because I haven't needed it. */
USB_ERROR_STR(-ENOSYS, "usb_reset called, unimplemented on BSD");
}
+98
View File
@@ -0,0 +1,98 @@
/* config.h. Generated by configure. */
/* config.h.in. Generated from configure.in by autoheader. */
#define LINUX_API 1
#define BSD_API 0
#define DARWIN_API 0
/* #undef HAVE_OLD_DEV_USB_USB_H */
#define HAVE_LIMITS_H 1
#define HAVE_UNISTD_H 1
#define HAVE_VALUES_H 1
#define LIBUSB_MAJOR_VERSION 0
#define LIBUSB_MINOR_VERSION 1
#define LIBUSB_MICRO_VERSION 12
#define LIBUSB_INTERFACE_AGE 4
#define LIBUSB_BINARY_AGE 8
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <values.h> header file. */
#define HAVE_VALUES_H 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "libusb"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME "libusb"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libusb 0.1.12"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libusb"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.1.12"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.1.12"
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
/* #undef WORDS_BIGENDIAN */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
+1209
View File
File diff suppressed because it is too large. Load diff
+520
View File
@@ -0,0 +1,520 @@
/*
* Parses descriptors
*
* Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is covered by the LGPL, read LICENSE for details.
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "usbi.h"
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
unsigned char type, unsigned char index, void *buf, int size)
{
memset(buf, 0, size);
return usb_control_msg(udev, ep | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(type << 8) + index, 0, buf, size, 1000);
}
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size)
{
memset(buf, 0, size);
return usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(type << 8) + index, 0, buf, size, 1000);
}
int usb_parse_descriptor(unsigned char *source, char *description, void *dest)
{
unsigned char *sp = source, *dp = dest;
uint16_t w;
uint32_t d;
char *cp;
for (cp = description; *cp; cp++) {
switch (*cp) {
case 'b': /* 8-bit byte */
*dp++ = *sp++;
break;
case 'w': /* 16-bit word, convert from little endian to CPU */
w = (sp[1] << 8) | sp[0]; sp += 2;
dp += ((unsigned long)dp & 1); /* Align to word boundary */
*((uint16_t *)dp) = w; dp += 2;
break;
case 'd': /* 32-bit dword, convert from little endian to CPU */
d = (sp[3] << 24) | (sp[2] << 16) | (sp[1] << 8) | sp[0]; sp += 4;
dp += ((unsigned long)dp & 2); /* Align to dword boundary */
*((uint32_t *)dp) = d; dp += 4;
break;
/* These two characters are undocumented and just a hack for Linux */
case 'W': /* 16-bit word, keep CPU endianess */
dp += ((unsigned long)dp & 1); /* Align to word boundary */
memcpy(dp, sp, 2); sp += 2; dp += 2;
break;
case 'D': /* 32-bit dword, keep CPU endianess */
dp += ((unsigned long)dp & 2); /* Align to dword boundary */
memcpy(dp, sp, 4); sp += 4; dp += 4;
break;
}
}
return sp - source;
}
/*
* This code looks surprisingly similar to the code I wrote for the Linux
* kernel. It's not a coincidence :)
*/
static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
{
struct usb_descriptor_header header;
unsigned char *begin;
int parsed = 0, len, numskipped;
usb_parse_descriptor(buffer, "bb", &header);
/* Everything should be fine being passed into here, but we sanity */
/* check JIC */
if (header.bLength > size) {
if (usb_debug >= 1)
fprintf(stderr, "ran out of descriptors parsing\n");
return -1;
}
if (header.bDescriptorType != USB_DT_ENDPOINT) {
if (usb_debug >= 2)
fprintf(stderr, "unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X\n",
header.bDescriptorType, USB_DT_ENDPOINT);
return parsed;
}
if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
usb_parse_descriptor(buffer, "bbbbwbbb", endpoint);
else if (header.bLength >= ENDPOINT_DESC_LENGTH)
usb_parse_descriptor(buffer, "bbbbwb", endpoint);
buffer += header.bLength;
size -= header.bLength;
parsed += header.bLength;
/* Skip over the rest of the Class Specific or Vendor Specific */
/* descriptors */
begin = buffer;
numskipped = 0;
while (size >= DESC_HEADER_LENGTH) {
usb_parse_descriptor(buffer, "bb", &header);
if (header.bLength < 2) {
if (usb_debug >= 1)
fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
return -1;
}
/* If we find another "proper" descriptor then we're done */
if ((header.bDescriptorType == USB_DT_ENDPOINT) ||
(header.bDescriptorType == USB_DT_INTERFACE) ||
(header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE))
break;
if (usb_debug >= 1)
fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType);
numskipped++;
buffer += header.bLength;
size -= header.bLength;
parsed += header.bLength;
}
if (numskipped && usb_debug >= 2)
fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped);
/* Copy any unknown descriptors into a storage area for drivers */
/* to later parse */
len = (int)(buffer - begin);
if (!len) {
endpoint->extra = NULL;
endpoint->extralen = 0;
return parsed;
}
endpoint->extra = malloc(len);
if (!endpoint->extra) {
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for endpoint extra descriptors\n");
endpoint->extralen = 0;
return parsed;
}
memcpy(endpoint->extra, begin, len);
endpoint->extralen = len;
return parsed;
}
static int usb_parse_interface(struct usb_interface *interface,
unsigned char *buffer, int size)
{
int i, len, numskipped, retval, parsed = 0;
struct usb_descriptor_header header;
struct usb_interface_descriptor *ifp;
unsigned char *begin;
interface->num_altsetting = 0;
while (size >= INTERFACE_DESC_LENGTH) {
interface->altsetting = realloc(interface->altsetting, sizeof(struct usb_interface_descriptor) * (interface->num_altsetting + 1));
if (!interface->altsetting) {
if (usb_debug >= 1)
fprintf(stderr, "couldn't malloc interface->altsetting\n");
return -1;
}
ifp = interface->altsetting + interface->num_altsetting;
interface->num_altsetting++;
usb_parse_descriptor(buffer, "bbbbbbbbb", ifp);
/* Skip over the interface */
buffer += ifp->bLength;
parsed += ifp->bLength;
size -= ifp->bLength;
begin = buffer;
numskipped = 0;
/* Skip over any interface, class or vendor descriptors */
while (size >= DESC_HEADER_LENGTH) {
usb_parse_descriptor(buffer, "bb", &header);
if (header.bLength < 2) {
if (usb_debug >= 1)
fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
return -1;
}
/* If we find another "proper" descriptor then we're done */
if ((header.bDescriptorType == USB_DT_INTERFACE) ||
(header.bDescriptorType == USB_DT_ENDPOINT) ||
(header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE))
break;
numskipped++;
buffer += header.bLength;
parsed += header.bLength;
size -= header.bLength;
}
if (numskipped && usb_debug >= 2)
fprintf(stderr, "skipped %d class/vendor specific interface descriptors\n", numskipped);
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
len = (int)(buffer - begin);
if (!len) {
ifp->extra = NULL;
ifp->extralen = 0;
} else {
ifp->extra = malloc(len);
if (!ifp->extra) {
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for interface extra descriptors\n");
ifp->extralen = 0;
return -1;
}
memcpy(ifp->extra, begin, len);
ifp->extralen = len;
}
/* Did we hit an unexpected descriptor? */
usb_parse_descriptor(buffer, "bb", &header);
if ((size >= DESC_HEADER_LENGTH) &&
((header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE)))
return parsed;
if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
if (usb_debug >= 1)
fprintf(stderr, "too many endpoints\n");
return -1;
}
if (ifp->bNumEndpoints > 0) {
ifp->endpoint = (struct usb_endpoint_descriptor *)
malloc(ifp->bNumEndpoints *
sizeof(struct usb_endpoint_descriptor));
if (!ifp->endpoint) {
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for ifp->endpoint\n");
return -1;
}
memset(ifp->endpoint, 0, ifp->bNumEndpoints *
sizeof(struct usb_endpoint_descriptor));
for (i = 0; i < ifp->bNumEndpoints; i++) {
usb_parse_descriptor(buffer, "bb", &header);
if (header.bLength > size) {
if (usb_debug >= 1)
fprintf(stderr, "ran out of descriptors parsing\n");
return -1;
}
retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
if (retval < 0)
return retval;
buffer += retval;
parsed += retval;
size -= retval;
}
} else
ifp->endpoint = NULL;
/* We check to see if it's an alternate to this one */
ifp = (struct usb_interface_descriptor *)buffer;
if (size < USB_DT_INTERFACE_SIZE ||
ifp->bDescriptorType != USB_DT_INTERFACE ||
!ifp->bAlternateSetting)
return parsed;
}
return parsed;
}
int usb_parse_configuration(struct usb_config_descriptor *config,
unsigned char *buffer)
{
int i, retval, size;
struct usb_descriptor_header header;
usb_parse_descriptor(buffer, "bbwbbbbb", config);
size = config->wTotalLength;
if (config->bNumInterfaces > USB_MAXINTERFACES) {
if (usb_debug >= 1)
fprintf(stderr, "too many interfaces\n");
return -1;
}
config->interface = (struct usb_interface *)
malloc(config->bNumInterfaces *
sizeof(struct usb_interface));
if (!config->interface) {
if (usb_debug >= 1)
fprintf(stderr, "out of memory\n");
return -1;
}
memset(config->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface));
buffer += config->bLength;
size -= config->bLength;
config->extra = NULL;
config->extralen = 0;
for (i = 0; i < config->bNumInterfaces; i++) {
int numskipped, len;
unsigned char *begin;
/* Skip over the rest of the Class Specific or Vendor */
/* Specific descriptors */
begin = buffer;
numskipped = 0;
while (size >= DESC_HEADER_LENGTH) {
usb_parse_descriptor(buffer, "bb", &header);
if ((header.bLength > size) || (header.bLength < DESC_HEADER_LENGTH)) {
if (usb_debug >= 1)
fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
return -1;
}
/* If we find another "proper" descriptor then we're done */
if ((header.bDescriptorType == USB_DT_ENDPOINT) ||
(header.bDescriptorType == USB_DT_INTERFACE) ||
(header.bDescriptorType == USB_DT_CONFIG) ||
(header.bDescriptorType == USB_DT_DEVICE))
break;
if (usb_debug >= 2)
fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType);
numskipped++;
buffer += header.bLength;
size -= header.bLength;
}
if (numskipped && usb_debug >= 2)
fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped);
/* Copy any unknown descriptors into a storage area for */
/* drivers to later parse */
len = (int)(buffer - begin);
if (len) {
/* FIXME: We should realloc and append here */
if (!config->extralen) {
config->extra = malloc(len);
if (!config->extra) {
if (usb_debug >= 1)
fprintf(stderr, "couldn't allocate memory for config extra descriptors\n");
config->extralen = 0;
return -1;
}
memcpy(config->extra, begin, len);
config->extralen = len;
}
}
retval = usb_parse_interface(config->interface + i, buffer, size);
if (retval < 0)
return retval;
buffer += retval;
size -= retval;
}
return size;
}
void usb_destroy_configuration(struct usb_device *dev)
{
int c, i, j, k;
if (!dev->config)
return;
for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
struct usb_config_descriptor *cf = &dev->config[c];
if (!cf->interface)
continue;
for (i = 0; i < cf->bNumInterfaces; i++) {
struct usb_interface *ifp = &cf->interface[i];
if (!ifp->altsetting)
continue;
for (j = 0; j < ifp->num_altsetting; j++) {
struct usb_interface_descriptor *as = &ifp->altsetting[j];
if (as->extra)
free(as->extra);
if (!as->endpoint)
continue;
for (k = 0; k < as->bNumEndpoints; k++) {
if (as->endpoint[k].extra)
free(as->endpoint[k].extra);
}
free(as->endpoint);
}
free(ifp->altsetting);
}
free(cf->interface);
}
free(dev->config);
}
void usb_fetch_and_parse_descriptors(usb_dev_handle *udev)
{
struct usb_device *dev = udev->device;
int i;
if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
if (usb_debug >= 1)
fprintf(stderr, "Too many configurations (%d > %d)\n", dev->descriptor.bNumConfigurations, USB_MAXCONFIG);
return;
}
if (dev->descriptor.bNumConfigurations < 1) {
if (usb_debug >= 1)
fprintf(stderr, "Not enough configurations (%d < %d)\n", dev->descriptor.bNumConfigurations, 1);
return;
}
dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor));
if (!dev->config) {
if (usb_debug >= 1)
fprintf(stderr, "Unable to allocate memory for config descriptor\n");
return;
}
memset(dev->config, 0, dev->descriptor.bNumConfigurations *
sizeof(struct usb_config_descriptor));
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
unsigned char buffer[8], *bigbuffer;
struct usb_config_descriptor config;
int res;
/* Get the first 8 bytes so we can figure out what the total length is */
res = usb_get_descriptor(udev, USB_DT_CONFIG, i, buffer, 8);
if (res < 8) {
if (usb_debug >= 1) {
if (res < 0)
fprintf(stderr, "Unable to get descriptor (%d)\n", res);
else
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, res);
}
goto err;
}
usb_parse_descriptor(buffer, "bbw", &config);
bigbuffer = malloc(config.wTotalLength);
if (!bigbuffer) {
if (usb_debug >= 1)
fprintf(stderr, "Unable to allocate memory for descriptors\n");
goto err;
}
res = usb_get_descriptor(udev, USB_DT_CONFIG, i, bigbuffer, config.wTotalLength);
if (res < config.wTotalLength) {
if (usb_debug >= 1) {
if (res < 0)
fprintf(stderr, "Unable to get descriptor (%d)\n", res);
else
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, res);
}
free(bigbuffer);
goto err;
}
res = usb_parse_configuration(&dev->config[i], bigbuffer);
if (usb_debug >= 2) {
if (res > 0)
fprintf(stderr, "Descriptor data still left\n");
else if (res < 0)
fprintf(stderr, "Unable to parse descriptors\n");
}
free(bigbuffer);
}
return;
err:
free(dev->config);
dev->config = NULL;
}
+36
View File
@@ -0,0 +1,36 @@
/*
* USB Error messages
*
* Copyright (c) 2000-2001 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is covered by the LGPL, read LICENSE for details.
*/
#include <errno.h>
#include <string.h>
#include "usb.h"
#include "error.h"
char usb_error_str[1024] = "";
int usb_error_errno = 0;
usb_error_type_t usb_error_type = USB_ERROR_TYPE_NONE;
char *usb_strerror(void)
{
switch (usb_error_type) {
case USB_ERROR_TYPE_NONE:
return "No error";
case USB_ERROR_TYPE_STRING:
return usb_error_str;
case USB_ERROR_TYPE_ERRNO:
if (usb_error_errno > -USB_ERROR_BEGIN)
return strerror(usb_error_errno);
else
/* Any error we don't know falls under here */
return "Unknown error";
}
return "Unknown error";
}
+31
View File
@@ -0,0 +1,31 @@
#ifndef _ERROR_H_
#define _ERROR_H_
typedef enum {
USB_ERROR_TYPE_NONE = 0,
USB_ERROR_TYPE_STRING,
USB_ERROR_TYPE_ERRNO,
} usb_error_type_t;
extern char usb_error_str[1024];
extern int usb_error_errno;
extern usb_error_type_t usb_error_type;
#define USB_ERROR(x) \
do { \
usb_error_type = USB_ERROR_TYPE_ERRNO; \
usb_error_errno = x; \
return x; \
} while (0)
#define USB_ERROR_STR(x, format, args...) \
do { \
usb_error_type = USB_ERROR_TYPE_STRING; \
snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \
if (usb_debug >= 2) \
fprintf(stderr, "USB error: %s\n", usb_error_str); \
return x; \
} while (0)
#endif /* _ERROR_H_ */
+733
View File
@@ -0,0 +1,733 @@
/*
* Linux USB support
*
* Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is covered by the LGPL, read LICENSE for details.
*/
#include <stdlib.h> /* getenv, etc */
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <dirent.h>
#include "linux.h"
#include "usbi.h"
static char usb_path[PATH_MAX + 1] = "";
static int device_open(struct usb_device *dev)
{
char filename[PATH_MAX + 1];
int fd;
snprintf(filename, sizeof(filename) - 1, "%s/%s/%s",
usb_path, dev->bus->dirname, dev->filename);
fd = open(filename, O_RDWR);
if (fd < 0) {
fd = open(filename, O_RDONLY);
if (fd < 0)
USB_ERROR_STR(-errno, "failed to open %s: %s",
filename, strerror(errno));
}
return fd;
}
int usb_os_open(usb_dev_handle *dev)
{
dev->fd = device_open(dev->device);
return 0;
}
int usb_os_close(usb_dev_handle *dev)
{
if (dev->fd < 0)
return 0;
if (close(dev->fd) == -1)
/* Failing trying to close a file really isn't an error, so return 0 */
USB_ERROR_STR(0, "tried to close device fd %d: %s", dev->fd,
strerror(errno));
return 0;
}
int usb_set_configuration(usb_dev_handle *dev, int configuration)
{
int ret;
ret = ioctl(dev->fd, IOCTL_USB_SETCONFIG, &configuration);
if (ret < 0)
USB_ERROR_STR(-errno, "could not set config %d: %s", configuration,
strerror(errno));
dev->config = configuration;
return 0;
}
int usb_claim_interface(usb_dev_handle *dev, int interface)
{
int ret;
ret = ioctl(dev->fd, IOCTL_USB_CLAIMINTF, &interface);
if (ret < 0) {
if (errno == EBUSY && usb_debug > 0)
fprintf(stderr, "Check that you have permissions to write to %s/%s and, if you don't, that you set up hotplug (http://linux-hotplug.sourceforge.net/) correctly.\n", dev->bus->dirname, dev->device->filename);
USB_ERROR_STR(-errno, "could not claim interface %d: %s", interface,
strerror(errno));
}
dev->interface = interface;
return 0;
}
int usb_release_interface(usb_dev_handle *dev, int interface)
{
int ret;
ret = ioctl(dev->fd, IOCTL_USB_RELEASEINTF, &interface);
if (ret < 0)
USB_ERROR_STR(-errno, "could not release intf %d: %s", interface,
strerror(errno));
dev->interface = -1;
return 0;
}
int usb_set_altinterface(usb_dev_handle *dev, int alternate)
{
int ret;
struct usb_setinterface setintf;
if (dev->interface < 0)
USB_ERROR(-EINVAL);
setintf.interface = dev->interface;
setintf.altsetting = alternate;
ret = ioctl(dev->fd, IOCTL_USB_SETINTF, &setintf);
if (ret < 0)
USB_ERROR_STR(-errno, "could not set alt intf %d/%d: %s",
dev->interface, alternate, strerror(errno));
dev->altsetting = alternate;
return 0;
}
/*
* Linux usbfs has a limit of one page size for synchronous bulk read/write.
* 4096 is the most portable maximum we can do for now.
* Linux usbfs has a limit of 16KB for the URB interface. We use this now
* to get better performance for USB 2.0 devices.
*/
#define MAX_READ_WRITE (16 * 1024)
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
int value, int index, char *bytes, int size, int timeout)
{
struct usb_ctrltransfer ctrl;
int ret;
ctrl.bRequestType = requesttype;
ctrl.bRequest = request;
ctrl.wValue = value;
ctrl.wIndex = index;
ctrl.wLength = size;
ctrl.data = bytes;
ctrl.timeout = timeout;
ret = ioctl(dev->fd, IOCTL_USB_CONTROL, &ctrl);
if (ret < 0)
USB_ERROR_STR(-errno, "error sending control message: %s", strerror(errno));
return ret;
}
#define URB_USERCONTEXT_COOKIE ((void *)0x1)
/* Reading and writing are the same except for the endpoint */
static int usb_urb_transfer(usb_dev_handle *dev, int ep, int urbtype,
char *bytes, int size, int timeout)
{
struct usb_urb urb;
int bytesdone = 0, requested;
struct timeval tv, tv_ref, tv_now;
struct usb_urb *context;
int ret, waiting;
/*
* HACK: The use of urb.usercontext is a hack to get threaded applications
* sort of working again. Threaded support is still not recommended, but
* this should allow applications to work in the common cases. Basically,
* if we get the completion for an URB we're not waiting for, then we update
* the usercontext pointer to 1 for the other threads URB and it will see
* the change after it wakes up from the the timeout. Ugly, but it works.
*/
/*
* Get actual time, and add the timeout value. The result is the absolute
* time where we have to quit waiting for an message.
*/
gettimeofday(&tv_ref, NULL);
tv_ref.tv_sec = tv_ref.tv_sec + timeout / 1000;
tv_ref.tv_usec = tv_ref.tv_usec + (timeout % 1000) * 1000;
if (tv_ref.tv_usec > 1000000) {
tv_ref.tv_usec -= 1000000;
tv_ref.tv_sec++;
}
do {
fd_set writefds;
requested = size - bytesdone;
if (requested > MAX_READ_WRITE)
requested = MAX_READ_WRITE;
urb.type = urbtype;
urb.endpoint = ep;
urb.flags = 0;
urb.buffer = bytes + bytesdone;
urb.buffer_length = requested;
urb.signr = 0;
urb.actual_length = 0;
urb.number_of_packets = 0; /* don't do isochronous yet */
urb.usercontext = NULL;
ret = ioctl(dev->fd, IOCTL_USB_SUBMITURB, &urb);
if (ret < 0) {
USB_ERROR_STR(-errno, "error submitting URB: %s", strerror(errno));
return ret;
}
FD_ZERO(&writefds);
FD_SET(dev->fd, &writefds);
restart:
waiting = 1;
context = NULL;
while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) {
tv.tv_sec = 0;
tv.tv_usec = 1000; // 1 msec
select(dev->fd + 1, NULL, &writefds, NULL, &tv); //sub second wait
if (timeout) {
/* compare with actual time, as the select timeout is not that precise */
gettimeofday(&tv_now, NULL);
if ((tv_now.tv_sec > tv_ref.tv_sec) ||
((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec)))
waiting = 0;
}
}
if (context && context != &urb) {
context->usercontext = URB_USERCONTEXT_COOKIE;
/* We need to restart since we got a successful URB, but not ours */
goto restart;
}
/*
* If there was an error, that wasn't EAGAIN (no completion), then
* something happened during the reaping and we should return that
* error now
*/
if (ret < 0 && !urb.usercontext && errno != EAGAIN)
USB_ERROR_STR(-errno, "error reaping URB: %s", strerror(errno));
bytesdone += urb.actual_length;
} while ((ret == 0 || urb.usercontext) && bytesdone < size && urb.actual_length == requested);
/* If the URB didn't complete in success or error, then let's unlink it */
if (ret < 0 && !urb.usercontext) {
int rc;
if (!waiting)
rc = -ETIMEDOUT;
else
rc = urb.status;
ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb);
if (ret < 0 && errno != EINVAL && usb_debug >= 1)
fprintf(stderr, "error discarding URB: %s", strerror(errno));
/*
* When the URB is unlinked, it gets moved to the completed list and
* then we need to reap it or else the next time we call this function,
* we'll get the previous completion and exit early
*/
ioctl(dev->fd, IOCTL_USB_REAPURB, &context);
return rc;
}
return bytesdone;
}
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
/* Ensure the endpoint address is correct */
return usb_urb_transfer(dev, ep, USB_URB_TYPE_BULK, bytes, size,
timeout);
}
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
/* Ensure the endpoint address is correct */
ep |= USB_ENDPOINT_IN;
return usb_urb_transfer(dev, ep, USB_URB_TYPE_BULK, bytes, size,
timeout);
}
/*
* FIXME: Packetize large buffers here. 2.4 HCDs (atleast, haven't checked
* 2.5 HCDs yet) don't handle multi-packet Interrupt transfers. So we need
* to lookup the endpoint packet size and packetize appropriately here.
*/
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
/* Ensure the endpoint address is correct */
return usb_urb_transfer(dev, ep, USB_URB_TYPE_INTERRUPT, bytes, size,
timeout);
}
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
/* Ensure the endpoint address is correct */
ep |= USB_ENDPOINT_IN;
return usb_urb_transfer(dev, ep, USB_URB_TYPE_INTERRUPT, bytes, size,
timeout);
}
int usb_os_find_busses(struct usb_bus **busses)
{
struct usb_bus *fbus = NULL;
DIR *dir;
struct dirent *entry;
dir = opendir(usb_path);
if (!dir)
USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", usb_path,
strerror(errno));
while ((entry = readdir(dir)) != NULL) {
struct usb_bus *bus;
/* Skip anything starting with a . */
if (entry->d_name[0] == '.')
continue;
if (!strchr("0123456789", entry->d_name[strlen(entry->d_name) - 1])) {
if (usb_debug >= 2)
fprintf(stderr, "usb_os_find_busses: Skipping non bus directory %s\n",
entry->d_name);
continue;
}
bus = malloc(sizeof(*bus));
if (!bus)
USB_ERROR(-ENOMEM);
memset((void *)bus, 0, sizeof(*bus));
strncpy(bus->dirname, entry->d_name, sizeof(bus->dirname) - 1);
bus->dirname[sizeof(bus->dirname) - 1] = 0;
LIST_ADD(fbus, bus);
if (usb_debug >= 2)
fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
}
closedir(dir);
*busses = fbus;
return 0;
}
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
{
struct usb_device *fdev = NULL;
DIR *dir;
struct dirent *entry;
char dirpath[PATH_MAX + 1];
snprintf(dirpath, PATH_MAX, "%s/%s", usb_path, bus->dirname);
dir = opendir(dirpath);
if (!dir)
USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", dirpath,
strerror(errno));
while ((entry = readdir(dir)) != NULL) {
unsigned char device_desc[DEVICE_DESC_LENGTH];
char filename[PATH_MAX + 1];
struct usb_device *dev;
struct usb_connectinfo connectinfo;
int i, fd, ret;
/* Skip anything starting with a . */
if (entry->d_name[0] == '.')
continue;
dev = malloc(sizeof(*dev));
if (!dev)
USB_ERROR(-ENOMEM);
memset((void *)dev, 0, sizeof(*dev));
dev->bus = bus;
strncpy(dev->filename, entry->d_name, sizeof(dev->filename) - 1);
dev->filename[sizeof(dev->filename) - 1] = 0;
snprintf(filename, sizeof(filename) - 1, "%s/%s", dirpath, entry->d_name);
fd = open(filename, O_RDWR);
if (fd < 0) {
fd = open(filename, O_RDONLY);
if (fd < 0) {
if (usb_debug >= 2)
fprintf(stderr, "usb_os_find_devices: Couldn't open %s\n",
filename);
free(dev);
continue;
}
}
/* Get the device number */
ret = ioctl(fd, IOCTL_USB_CONNECTINFO, &connectinfo);
if (ret < 0) {
if (usb_debug)
fprintf(stderr, "usb_os_find_devices: couldn't get connect info\n");
} else
dev->devnum = connectinfo.devnum;
ret = read(fd, (void *)device_desc, DEVICE_DESC_LENGTH);
if (ret < 0) {
if (usb_debug)
fprintf(stderr, "usb_os_find_devices: Couldn't read descriptor\n");
free(dev);
goto err;
}
/*
* Linux kernel converts the words in this descriptor to CPU endian, so
* we use the undocumented W character for usb_parse_descriptor() that
* doesn't convert endianess when parsing the descriptor
*/
usb_parse_descriptor(device_desc, "bbWbbbbWWWbbbb", &dev->descriptor);
LIST_ADD(fdev, dev);
if (usb_debug >= 2)
fprintf(stderr, "usb_os_find_devices: Found %s on %s\n",
dev->filename, bus->dirname);
/* Now try to fetch the rest of the descriptors */
if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG)
/* Silent since we'll try again later */
goto err;
if (dev->descriptor.bNumConfigurations < 1)
/* Silent since we'll try again later */
goto err;
dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor));
if (!dev->config)
/* Silent since we'll try again later */
goto err;
memset(dev->config, 0, dev->descriptor.bNumConfigurations *
sizeof(struct usb_config_descriptor));
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
unsigned char buffer[8], *bigbuffer;
struct usb_config_descriptor config;
/* Get the first 8 bytes so we can figure out what the total length is */
ret = read(fd, (void *)buffer, 8);
if (ret < 8) {
if (usb_debug >= 1) {
if (ret < 0)
fprintf(stderr, "Unable to get descriptor (%d)\n", ret);
else
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, ret);
}
goto err;
}
usb_parse_descriptor(buffer, "bbw", &config);
bigbuffer = malloc(config.wTotalLength);
if (!bigbuffer) {
if (usb_debug >= 1)
fprintf(stderr, "Unable to allocate memory for descriptors\n");
goto err;
}
/* Read the rest of the config descriptor */
memcpy(bigbuffer, buffer, 8);
ret = read(fd, (void *)(bigbuffer + 8), config.wTotalLength - 8);
if (ret < config.wTotalLength - 8) {
if (usb_debug >= 1) {
if (ret < 0)
fprintf(stderr, "Unable to get descriptor (%d)\n", ret);
else
fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, ret);
}
free(bigbuffer);
goto err;
}
ret = usb_parse_configuration(&dev->config[i], bigbuffer);
if (usb_debug >= 2) {
if (ret > 0)
fprintf(stderr, "Descriptor data still left\n");
else if (ret < 0)
fprintf(stderr, "Unable to parse descriptors\n");
}
free(bigbuffer);
}
err:
close(fd);
}
closedir(dir);
*devices = fdev;
return 0;
}
int usb_os_determine_children(struct usb_bus *bus)
{
struct usb_device *dev, *devices[256];
struct usb_ioctl command;
int ret, i, i1;
/* Create a list of devices first */
memset(devices, 0, sizeof(devices));
for (dev = bus->devices; dev; dev = dev->next)
if (dev->devnum)
devices[dev->devnum] = dev;
/* Now fetch the children for each device */
for (dev = bus->devices; dev; dev = dev->next) {
struct usb_hub_portinfo portinfo;
int fd;
fd = device_open(dev);
if (fd < 0)
continue;
/* Query the hub driver for the children of this device */
if (dev->config && dev->config->interface && dev->config->interface->altsetting)
command.ifno = dev->config->interface->altsetting->bInterfaceNumber;
else
command.ifno = 0;
command.ioctl_code = IOCTL_USB_HUB_PORTINFO;
command.data = &portinfo;
ret = ioctl(fd, IOCTL_USB_IOCTL, &command);
if (ret < 0) {
/* errno == ENOSYS means the device probably wasn't a hub */
if (errno != ENOSYS && usb_debug > 1)
fprintf(stderr, "error obtaining child information: %s\n",
strerror(errno));
close(fd);
continue;
}
dev->num_children = 0;
for (i = 0; i < portinfo.numports; i++)
if (portinfo.port[i])
dev->num_children++;
/* Free any old children first */
free(dev->children);
dev->children = malloc(sizeof(struct usb_device *) * dev->num_children);
if (!dev->children) {
if (usb_debug > 1)
fprintf(stderr, "error allocating %zu bytes memory for dev->children\n",
sizeof(struct usb_device *) * dev->num_children);
dev->num_children = 0;
close(fd);
continue;
}
for (i = 0, i1 = 0; i < portinfo.numports; i++) {
if (!portinfo.port[i])
continue;
dev->children[i1++] = devices[portinfo.port[i]];
devices[portinfo.port[i]] = NULL;
}
close(fd);
}
/*
* There should be one device left in the devices list and that should be
* the root device
*/
for (i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
if (devices[i])
bus->root_dev = devices[i];
}
return 0;
}
static int check_usb_vfs(const char *dirname)
{
DIR *dir;
struct dirent *entry;
int found = 0;
dir = opendir(dirname);
if (!dir)
return 0;
while ((entry = readdir(dir)) != NULL) {
/* Skip anything starting with a . */
if (entry->d_name[0] == '.')
continue;
/* We assume if we find any files that it must be the right place */
found = 1;
break;
}
closedir(dir);
return found;
}
void usb_os_init(void)
{
/* Find the path to the virtual filesystem */
if (getenv("USB_DEVFS_PATH")) {
if (check_usb_vfs(getenv("USB_DEVFS_PATH"))) {
strncpy(usb_path, getenv("USB_DEVFS_PATH"), sizeof(usb_path) - 1);
usb_path[sizeof(usb_path) - 1] = 0;
} else if (usb_debug)
fprintf(stderr, "usb_os_init: couldn't find USB VFS in USB_DEVFS_PATH\n");
}
if (!usb_path[0]) {
if (check_usb_vfs("/dev/bus/usb")) {
strncpy(usb_path, "/dev/bus/usb", sizeof(usb_path) - 1);
usb_path[sizeof(usb_path) - 1] = 0;
} else if (check_usb_vfs("/proc/bus/usb")) {
strncpy(usb_path, "/proc/bus/usb", sizeof(usb_path) - 1);
usb_path[sizeof(usb_path) - 1] = 0;
} else
usb_path[0] = 0; /* No path, no USB support */
}
if (usb_debug) {
if (usb_path[0])
fprintf(stderr, "usb_os_init: Found USB VFS at %s\n", usb_path);
else
fprintf(stderr, "usb_os_init: No USB VFS found, is it mounted?\n");
}
}
int usb_resetep(usb_dev_handle *dev, unsigned int ep)
{
int ret;
ret = ioctl(dev->fd, IOCTL_USB_RESETEP, &ep);
if (ret)
USB_ERROR_STR(-errno, "could not reset ep %d: %s", ep,
strerror(errno));
return 0;
}
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
{
int ret;
ret = ioctl(dev->fd, IOCTL_USB_CLEAR_HALT, &ep);
if (ret)
USB_ERROR_STR(-errno, "could not clear/halt ep %d: %s", ep,
strerror(errno));
return 0;
}
int usb_reset(usb_dev_handle *dev)
{
int ret;
ret = ioctl(dev->fd, IOCTL_USB_RESET, NULL);
if (ret)
USB_ERROR_STR(-errno, "could not reset: %s", strerror(errno));
return 0;
}
int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name,
unsigned int namelen)
{
struct usb_getdriver getdrv;
int ret;
getdrv.interface = interface;
ret = ioctl(dev->fd, IOCTL_USB_GETDRIVER, &getdrv);
if (ret)
USB_ERROR_STR(-errno, "could not get bound driver: %s", strerror(errno));
strncpy(name, getdrv.driver, namelen - 1);
name[namelen - 1] = 0;
return 0;
}
int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface)
{
struct usb_ioctl command;
int ret;
command.ifno = interface;
command.ioctl_code = IOCTL_USB_DISCONNECT;
command.data = NULL;
ret = ioctl(dev->fd, IOCTL_USB_IOCTL, &command);
if (ret)
USB_ERROR_STR(-errno, "could not detach kernel driver from interface %d: %s",
interface, strerror(errno));
return 0;
}
+119
View File
@@ -0,0 +1,119 @@
#ifndef __LINUX_H__
#define __LINUX_H__
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
struct usb_ctrltransfer {
/* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */
u_int8_t bRequestType;
u_int8_t bRequest;
u_int16_t wValue;
u_int16_t wIndex;
u_int16_t wLength;
u_int32_t timeout; /* in milliseconds */
/* pointer to data */
void *data;
};
struct usb_bulktransfer {
/* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */
unsigned int ep;
unsigned int len;
unsigned int timeout; /* in milliseconds */
/* pointer to data */
void *data;
};
struct usb_setinterface {
/* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */
unsigned int interface;
unsigned int altsetting;
};
#define USB_MAXDRIVERNAME 255
struct usb_getdriver {
unsigned int interface;
char driver[USB_MAXDRIVERNAME + 1];
};
#define USB_URB_DISABLE_SPD 1
#define USB_URB_ISO_ASAP 2
#define USB_URB_QUEUE_BULK 0x10
#define USB_URB_TYPE_ISO 0
#define USB_URB_TYPE_INTERRUPT 1
#define USB_URB_TYPE_CONTROL 2
#define USB_URB_TYPE_BULK 3
struct usb_iso_packet_desc {
unsigned int length;
unsigned int actual_length;
unsigned int status;
};
struct usb_urb {
unsigned char type;
unsigned char endpoint;
int status;
unsigned int flags;
void *buffer;
int buffer_length;
int actual_length;
int start_frame;
int number_of_packets;
int error_count;
unsigned int signr; /* signal to be sent on error, -1 if none should be sent */
void *usercontext;
struct usb_iso_packet_desc iso_frame_desc[0];
};
struct usb_connectinfo {
unsigned int devnum;
unsigned char slow;
};
struct usb_ioctl {
int ifno; /* interface 0..N ; negative numbers reserved */
int ioctl_code; /* MUST encode size + direction of data so the
* macros in <asm/ioctl.h> give correct values */
void *data; /* param buffer (in, or out) */
};
struct usb_hub_portinfo {
unsigned char numports;
unsigned char port[127]; /* port to device num mapping */
};
#define IOCTL_USB_CONTROL _IOWR('U', 0, struct usb_ctrltransfer)
#define IOCTL_USB_BULK _IOWR('U', 2, struct usb_bulktransfer)
#define IOCTL_USB_RESETEP _IOR('U', 3, unsigned int)
#define IOCTL_USB_SETINTF _IOR('U', 4, struct usb_setinterface)
#define IOCTL_USB_SETCONFIG _IOR('U', 5, unsigned int)
#define IOCTL_USB_GETDRIVER _IOW('U', 8, struct usb_getdriver)
#define IOCTL_USB_SUBMITURB _IOR('U', 10, struct usb_urb)
#define IOCTL_USB_DISCARDURB _IO('U', 11)
#define IOCTL_USB_REAPURB _IOW('U', 12, void *)
#define IOCTL_USB_REAPURBNDELAY _IOW('U', 13, void *)
#define IOCTL_USB_CLAIMINTF _IOR('U', 15, unsigned int)
#define IOCTL_USB_RELEASEINTF _IOR('U', 16, unsigned int)
#define IOCTL_USB_CONNECTINFO _IOW('U', 17, struct usb_connectinfo)
#define IOCTL_USB_IOCTL _IOWR('U', 18, struct usb_ioctl)
#define IOCTL_USB_HUB_PORTINFO _IOR('U', 19, struct usb_hub_portinfo)
#define IOCTL_USB_RESET _IO('U', 20)
#define IOCTL_USB_CLEAR_HALT _IOR('U', 21, unsigned int)
#define IOCTL_USB_DISCONNECT _IO('U', 22)
#define IOCTL_USB_CONNECT _IO('U', 23)
/*
* IOCTL_USB_HUB_PORTINFO, IOCTL_USB_DISCONNECT and IOCTL_USB_CONNECT
* all work via IOCTL_USB_IOCTL
*/
#endif
+307
View File
@@ -0,0 +1,307 @@
/*
* Main API entry point
*
* Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is covered by the LGPL, read LICENSE for details.
*/
#include <stdlib.h> /* getenv */
#include <stdio.h> /* stderr */
#include <string.h> /* strcmp */
#include <errno.h>
#include "usbi.h"
int usb_debug = 0;
struct usb_bus *usb_busses = NULL;
int usb_find_busses(void)
{
struct usb_bus *busses, *bus;
int ret, changes = 0;
ret = usb_os_find_busses(&busses);
if (ret < 0)
return ret;
/*
* Now walk through all of the busses we know about and compare against
* this new list. Any duplicates will be removed from the new list.
* If we don't find it in the new list, the bus was removed. Any
* busses still in the new list, are new to us.
*/
bus = usb_busses;
while (bus) {
int found = 0;
struct usb_bus *nbus, *tbus = bus->next;
nbus = busses;
while (nbus) {
struct usb_bus *tnbus = nbus->next;
if (!strcmp(bus->dirname, nbus->dirname)) {
/* Remove it from the new busses list */
LIST_DEL(busses, nbus);
usb_free_bus(nbus);
found = 1;
break;
}
nbus = tnbus;
}
if (!found) {
/* The bus was removed from the system */
LIST_DEL(usb_busses, bus);
usb_free_bus(bus);
changes++;
}
bus = tbus;
}
/*
* Anything on the *busses list is new. So add them to usb_busses and
* process them like the new bus it is.
*/
bus = busses;
while (bus) {
struct usb_bus *tbus = bus->next;
/*
* Remove it from the temporary list first and add it to the real
* usb_busses list.
*/
LIST_DEL(busses, bus);
LIST_ADD(usb_busses, bus);
changes++;
bus = tbus;
}
return changes;
}
int usb_find_devices(void)
{
struct usb_bus *bus;
int ret, changes = 0;
for (bus = usb_busses; bus; bus = bus->next) {
struct usb_device *devices, *dev;
/* Find all of the devices and put them into a temporary list */
ret = usb_os_find_devices(bus, &devices);
if (ret < 0)
return ret;
/*
* Now walk through all of the devices we know about and compare
* against this new list. Any duplicates will be removed from the new
* list. If we don't find it in the new list, the device was removed.
* Any devices still in the new list, are new to us.
*/
dev = bus->devices;
while (dev) {
int found = 0;
struct usb_device *ndev, *tdev = dev->next;
ndev = devices;
while (ndev) {
struct usb_device *tndev = ndev->next;
if (!strcmp(dev->filename, ndev->filename)) {
/* Remove it from the new devices list */
LIST_DEL(devices, ndev);
usb_free_dev(ndev);
found = 1;
break;
}
ndev = tndev;
}
if (!found) {
/* The device was removed from the system */
LIST_DEL(bus->devices, dev);
usb_free_dev(dev);
changes++;
}
dev = tdev;
}
/*
* Anything on the *devices list is new. So add them to bus->devices and
* process them like the new device it is.
*/
dev = devices;
while (dev) {
struct usb_device *tdev = dev->next;
/*
* Remove it from the temporary list first and add it to the real
* bus->devices list.
*/
LIST_DEL(devices, dev);
LIST_ADD(bus->devices, dev);
/*
* Some ports fetch the descriptors on scanning (like Linux) so we don't
* need to fetch them again.
*/
if (!dev->config) {
usb_dev_handle *udev;
udev = usb_open(dev);
if (udev) {
usb_fetch_and_parse_descriptors(udev);
usb_close(udev);
}
}
changes++;
dev = tdev;
}
usb_os_determine_children(bus);
}
return changes;
}
void usb_set_debug(int level)
{
if (usb_debug || level)
fprintf(stderr, "usb_set_debug: Setting debugging level to %d (%s)\n",
level, level ? "on" : "off");
usb_debug = level;
}
void usb_init(void)
{
if (getenv("USB_DEBUG"))
usb_set_debug(atoi(getenv("USB_DEBUG")));
usb_os_init();
}
usb_dev_handle *usb_open(struct usb_device *dev)
{
usb_dev_handle *udev;
udev = malloc(sizeof(*udev));
if (!udev)
return NULL;
udev->fd = -1;
udev->device = dev;
udev->bus = dev->bus;
udev->config = udev->interface = udev->altsetting = -1;
if (usb_os_open(udev) < 0) {
free(udev);
return NULL;
}
return udev;
}
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
size_t buflen)
{
/*
* We can't use usb_get_descriptor() because it's lacking the index
* parameter. This will be fixed in libusb 1.0
*/
return usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) + index, langid, buf, buflen, 1000);
}
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, size_t buflen)
{
char tbuf[255]; /* Some devices choke on size > 255 */
int ret, langid, si, di;
/*
* Asking for the zero'th index is special - it returns a string
* descriptor that contains all the language IDs supported by the
* device. Typically there aren't many - often only one. The
* language IDs are 16 bit numbers, and they start at the third byte
* in the descriptor. See USB 2.0 specification, section 9.6.7, for
* more information on this. */
ret = usb_get_string(dev, 0, 0, tbuf, sizeof(tbuf));
if (ret < 0)
return ret;
if (ret < 4)
return -EIO;
langid = tbuf[2] | (tbuf[3] << 8);
ret = usb_get_string(dev, index, langid, tbuf, sizeof(tbuf));
if (ret < 0)
return ret;
if (tbuf[1] != USB_DT_STRING)
return -EIO;
if (tbuf[0] > ret)
return -EFBIG;
for (di = 0, si = 2; si < tbuf[0]; si += 2) {
if (di >= (buflen - 1))
break;
if (tbuf[si + 1]) /* high byte */
buf[di++] = '?';
else
buf[di++] = tbuf[si];
}
buf[di] = 0;
return di;
}
int usb_close(usb_dev_handle *dev)
{
int ret;
ret = usb_os_close(dev);
free(dev);
return ret;
}
struct usb_device *usb_device(usb_dev_handle *dev)
{
return dev->device;
}
void usb_free_dev(struct usb_device *dev)
{
usb_destroy_configuration(dev);
free(dev->children);
free(dev);
}
struct usb_bus *usb_get_busses(void)
{
return usb_busses;
}
void usb_free_bus(struct usb_bus *bus)
{
free(bus);
}
+337
View File
@@ -0,0 +1,337 @@
/*
* Prototypes, structure definitions and macros.
*
* Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
*
* This library is covered by the LGPL, read LICENSE for details.
*
* This file (and only this file) may alternatively be licensed under the
* BSD license as well, read LICENSE for details.
*/
#ifndef __USB_H__
#define __USB_H__
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <dirent.h>
/*
* USB spec information
*
* This is all stuff grabbed from various USB specs and is pretty much
* not subject to change
*/
/*
* Device and/or Interface Class codes
*/
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
#define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PRINTER 7
#define USB_CLASS_PTP 6
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
#define USB_CLASS_DATA 10
#define USB_CLASS_VENDOR_SPEC 0xff
/*
* Descriptor types
*/
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
#define USB_DT_HID 0x21
#define USB_DT_REPORT 0x22
#define USB_DT_PHYSICAL 0x23
#define USB_DT_HUB 0x29
/*
* Descriptor sizes per descriptor type
*/
#define USB_DT_DEVICE_SIZE 18
#define USB_DT_CONFIG_SIZE 9
#define USB_DT_INTERFACE_SIZE 9
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
#define USB_DT_HUB_NONVAR_SIZE 7
/* All standard descriptors have these 2 fields in common */
struct usb_descriptor_header {
u_int8_t bLength;
u_int8_t bDescriptorType;
};
/* String descriptor */
struct usb_string_descriptor {
u_int8_t bLength;
u_int8_t bDescriptorType;
u_int16_t wData[1];
};
/* HID descriptor */
struct usb_hid_descriptor {
u_int8_t bLength;
u_int8_t bDescriptorType;
u_int16_t bcdHID;
u_int8_t bCountryCode;
u_int8_t bNumDescriptors;
/* u_int8_t bReportDescriptorType; */
/* u_int16_t wDescriptorLength; */
/* ... */
};
/* Endpoint descriptor */
#define USB_MAXENDPOINTS 32
struct usb_endpoint_descriptor {
u_int8_t bLength;
u_int8_t bDescriptorType;
u_int8_t bEndpointAddress;
u_int8_t bmAttributes;
u_int16_t wMaxPacketSize;
u_int8_t bInterval;
u_int8_t bRefresh;
u_int8_t bSynchAddress;
unsigned char *extra; /* Extra descriptors */
int extralen;
};
#define USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */
#define USB_ENDPOINT_DIR_MASK 0x80
#define USB_ENDPOINT_TYPE_MASK 0x03 /* in bmAttributes */
#define USB_ENDPOINT_TYPE_CONTROL 0
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 1
#define USB_ENDPOINT_TYPE_BULK 2
#define USB_ENDPOINT_TYPE_INTERRUPT 3
/* Interface descriptor */
#define USB_MAXINTERFACES 32
struct usb_interface_descriptor {
u_int8_t bLength;
u_int8_t bDescriptorType;
u_int8_t bInterfaceNumber;
u_int8_t bAlternateSetting;
u_int8_t bNumEndpoints;
u_int8_t bInterfaceClass;
u_int8_t bInterfaceSubClass;
u_int8_t bInterfaceProtocol;
u_int8_t iInterface;
struct usb_endpoint_descriptor *endpoint;
unsigned char *extra; /* Extra descriptors */
int extralen;
};
#define USB_MAXALTSETTING 128 /* Hard limit */
struct usb_interface {
struct usb_interface_descriptor *altsetting;
int num_altsetting;
};
/* Configuration descriptor information.. */
#define USB_MAXCONFIG 8
struct usb_config_descriptor {
u_int8_t bLength;
u_int8_t bDescriptorType;
u_int16_t wTotalLength;
u_int8_t bNumInterfaces;
u_int8_t bConfigurationValue;
u_int8_t iConfiguration;
u_int8_t bmAttributes;
u_int8_t MaxPower;
struct usb_interface *interface;
unsigned char *extra; /* Extra descriptors */
int extralen;
};
/* Device descriptor */
struct usb_device_descriptor {
u_int8_t bLength;
u_int8_t bDescriptorType;
u_int16_t bcdUSB;
u_int8_t bDeviceClass;
u_int8_t bDeviceSubClass;
u_int8_t bDeviceProtocol;
u_int8_t bMaxPacketSize0;
u_int16_t idVendor;
u_int16_t idProduct;
u_int16_t bcdDevice;
u_int8_t iManufacturer;
u_int8_t iProduct;
u_int8_t iSerialNumber;
u_int8_t bNumConfigurations;
};
struct usb_ctrl_setup {
u_int8_t bRequestType;
u_int8_t bRequest;
u_int16_t wValue;
u_int16_t wIndex;
u_int16_t wLength;
};
/*
* Standard requests
*/
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
/* 0x02 is reserved */
#define USB_REQ_SET_FEATURE 0x03
/* 0x04 is reserved */
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5)
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
/*
* Various libusb API related stuff
*/
#define USB_ENDPOINT_IN 0x80
#define USB_ENDPOINT_OUT 0x00
/* Error codes */
#define USB_ERROR_BEGIN 500000
/*
* This is supposed to look weird. This file is generated from autoconf
* and I didn't want to make this too complicated.
*/
#if 0
#define USB_LE16_TO_CPU(x) do { x = ((x & 0xff) << 8) | ((x & 0xff00) >> 8); } while(0)
#else
#define USB_LE16_TO_CPU(x)
#endif
/* Data types */
struct usb_device;
struct usb_bus;
/*
* To maintain compatibility with applications already built with libusb,
* we must only add entries to the end of this structure. NEVER delete or
* move members and only change types if you really know what you're doing.
*/
struct usb_device {
struct usb_device *next, *prev;
char filename[PATH_MAX + 1];
struct usb_bus *bus;
struct usb_device_descriptor descriptor;
struct usb_config_descriptor *config;
void *dev; /* Darwin support */
u_int8_t devnum;
unsigned char num_children;
struct usb_device **children;
};
struct usb_bus {
struct usb_bus *next, *prev;
char dirname[PATH_MAX + 1];
struct usb_device *devices;
u_int32_t location;
struct usb_device *root_dev;
};
struct usb_dev_handle;
typedef struct usb_dev_handle usb_dev_handle;
/* Variables */
extern struct usb_bus *usb_busses;
#ifdef __cplusplus
extern "C" {
#endif
/* Function prototypes */
/* usb.c */
usb_dev_handle *usb_open(struct usb_device *dev);
int usb_close(usb_dev_handle *dev);
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
size_t buflen);
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
size_t buflen);
/* descriptors.c */
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
unsigned char type, unsigned char index, void *buf, int size);
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size);
/* <arch>.c */
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
int value, int index, char *bytes, int size, int timeout);
int usb_set_configuration(usb_dev_handle *dev, int configuration);
int usb_claim_interface(usb_dev_handle *dev, int interface);
int usb_release_interface(usb_dev_handle *dev, int interface);
int usb_set_altinterface(usb_dev_handle *dev, int alternate);
int usb_resetep(usb_dev_handle *dev, unsigned int ep);
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
int usb_reset(usb_dev_handle *dev);
#if 1
#define LIBUSB_HAS_GET_DRIVER_NP 1
int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name,
unsigned int namelen);
#define LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP 1
int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface);
#endif
char *usb_strerror(void);
void usb_init(void);
void usb_set_debug(int level);
int usb_find_busses(void);
int usb_find_devices(void);
struct usb_device *usb_device(usb_dev_handle *dev);
struct usb_bus *usb_get_busses(void);
#ifdef __cplusplus
}
#endif
#endif /* __USB_H__ */
+74
View File
@@ -0,0 +1,74 @@
#ifndef _USBI_H_
#define _USBI_H_
#include "usb.h"
#include "error.h"
extern int usb_debug;
/* Some quick and generic macros for the simple kind of lists we use */
#define LIST_ADD(begin, ent) \
do { \
if (begin) { \
ent->next = begin; \
ent->next->prev = ent; \
} else \
ent->next = NULL; \
ent->prev = NULL; \
begin = ent; \
} while(0)
#define LIST_DEL(begin, ent) \
do { \
if (ent->prev) \
ent->prev->next = ent->next; \
else \
begin = ent->next; \
if (ent->next) \
ent->next->prev = ent->prev; \
ent->prev = NULL; \
ent->next = NULL; \
} while (0)
#define DESC_HEADER_LENGTH 2
#define DEVICE_DESC_LENGTH 18
#define CONFIG_DESC_LENGTH 9
#define INTERFACE_DESC_LENGTH 9
#define ENDPOINT_DESC_LENGTH 7
#define ENDPOINT_AUDIO_DESC_LENGTH 9
struct usb_dev_handle {
int fd;
struct usb_bus *bus;
struct usb_device *device;
int config;
int interface;
int altsetting;
/* Added by RMT so implementations can store other per-open-device data */
void *impl_info;
};
/* descriptors.c */
int usb_parse_descriptor(unsigned char *source, char *description, void *dest);
int usb_parse_configuration(struct usb_config_descriptor *config,
unsigned char *buffer);
void usb_fetch_and_parse_descriptors(usb_dev_handle *udev);
void usb_destroy_configuration(struct usb_device *dev);
/* OS specific routines */
int usb_os_find_busses(struct usb_bus **busses);
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices);
int usb_os_determine_children(struct usb_bus *bus);
void usb_os_init(void);
int usb_os_open(usb_dev_handle *dev);
int usb_os_close(usb_dev_handle *dev);
void usb_free_dev(struct usb_device *dev);
void usb_free_bus(struct usb_bus *bus);
#endif /* _USBI_H_ */
+855
View File
@@ -0,0 +1,855 @@
// -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
#ifndef __USBPP_HEADER__
#define __USBPP_HEADER__
#include <string>
#include <list>
#include <usb.h>
/*
* The following usb.h function is not wrapped yet:
* char *usb_strerror(void);
*/
/**
* \brief Classes to access Universal Serial Bus devices
*
* The USB Namespace provides a number of classes to work
* with Universal Serial Bus (USB) devices attached to the
* system.
*
* \author Brad Hards
*/
namespace USB {
class Device;
/**
* \brief Class representing a device endpoint
*
* This class represents a device endpoint. You need this class to
* perform bulk reads and writes.
*
*/
class Endpoint {
/**
* Busses is a friend because it fills in the descriptor type
* information on initialisation and rescan.
*/
friend class Busses;
public:
Endpoint() {};
#ifdef USE_UNTESTED_LIBUSBPP_METHODS
/**
* \brief Bulk write
*
* This method performs a bulk transfer to the endpoint.
*
* \param message is the message to be sent.
* \param timeout is the USB transaction timeout in milliseconds
*
* \returns the number of bytes sent, or a negative value on
* failure
*/
int bulkWrite(QByteArray message, int timeout = 100);
/**
* \brief Bulk read
*
* This method performs a bulk transfer from the endpoint.
*
* \param length is the maximum data transfer required.
* \param message is the message that was received.
* \param timeout is the USB transaction timeout in milliseconds
*
* \returns the number of bytes received, or a negative value on
* failure
*/
int bulkRead(int length, unsigned char *message, int timeout = 100);
/**
* \brief Reset endpoint
*
* This method resets the endpoint.
*/
int reset(void);
/**
* \brief Clear halt
*
* This method clears a halt (stall) on the endpoint.
*/
int clearHalt(void);
#endif /* USE_UNTESTED_LIBUSBPP_METHODS */
/**
* \brief Endpoint descriptor information output
*
* This method dumps out the various characteristics
* of the endpoint to standard output.
*
* It is mostly useful for debugging.
*/
void dumpDescriptor(void);
private:
void setDescriptor(struct usb_endpoint_descriptor);
void setParent(Device *parent);
u_int8_t m_Length;
u_int8_t m_DescriptorType;
u_int8_t m_EndpointAddress;
u_int8_t m_Attributes;
u_int16_t m_MaxPacketSize;
u_int8_t m_Interval;
u_int8_t m_Refresh;
u_int8_t m_SynchAddress;
Device *m_parent;
};
class AltSetting : public std::list<Endpoint *> {
/**
* Busses is a friend because it fills in the descriptor type
* information on initialisation and rescan.
*/
friend class Busses;
public:
AltSetting() {};
u_int8_t numEndpoints(void);
/**
* \brief AltSetting descriptor information output
*
* This method dumps out the various characteristics
* of the alternate setting to standard output.
*
* It is mostly useful for debugging.
*/
void dumpDescriptor(void);
Endpoint *firstEndpoint(void);
Endpoint *nextEndpoint(void);
Endpoint *lastEndpoint(void);
private:
std::list<Endpoint *>::const_iterator iter;
void setDescriptor(struct usb_interface_descriptor);
/* we don't use a normal usb_interface_descriptor */
/* because that would bring in the endpoint list */
u_int8_t m_Length;
u_int8_t m_DescriptorType;
u_int8_t m_InterfaceNumber;
u_int8_t m_AlternateSetting;
u_int8_t m_NumEndpoints;
u_int8_t m_InterfaceClass;
u_int8_t m_InterfaceSubClass;
u_int8_t m_InterfaceProtocol;
u_int8_t m_Interface;
};
/**
* \brief Class representing an interface of a Device
*
* The Interface class represents a USB interface
* for a device attached to a Universal Serial Bus.
*
* Interfaces are the main element of the USB class
* structure.
*
* \author Brad Hards
*/
class Interface : public std::list<AltSetting *> {
/**
* Busses is a friend because it fills in the descriptor type
* information on initialisation and rescan.
*/
friend class Busses;
public:
Interface() {};
#ifdef LIBUSB_HAS_GET_DRIVER_NP
/**
* \brief get the current driver for an interface
*
* \param driver a string containing the name of the current
* driver for the interface. You can typically pass in an empty
* string for this.
*
* \return length of string, or 0 on error.
*/
int driverName(std::string &driver);
#endif
#ifdef USE_UNTESTED_LIBUSBPP_METHODS
/**
* \brief Claim this interface
*
* This method claims the interface. You have to claim the
* interface before performing any operations on the interface (or
* on endpoints that are part of the interface).
*
* \return 0 on success or negative number on error.
*/
int claim(void);
/**
* \brief Release this interface
*
* This method releases the interface. You should release the
* interface after all operations on it (and any lower level
* endpoints) are completed.
*
* \return 0 on success or negative number on error.
*/
int release(void);
/**
* \brief Set interface alternate setting
*
* This method sets the interface to a particular AltSetting.
*
* \param altSettingNumber the AltSetting that the interface
* should be changed to.
*
* \return 0 on success, or a negative number in case of error.
*/
int setAltSetting(int altSettingNumber);
#endif /* USE_UNTESTED_LIBUSBPP_METHODS */
/**
* \brief Number of Alternative Settings that this interface has
*
* This is a simple accessor method that specifies the number
* alternative settings that this device interface has.
*/
u_int8_t numAltSettings(void);
/**
* \brief First AltSetting for the Interface
*
* This method returns a pointer to the first AltSetting
* for the Interface.
*
* See nextAltSetting() for an example of how it might be
* used.
*
* \see nextAltSetting(), lastAltSetting(), numAltSettings()
*/
AltSetting *firstAltSetting(void);
/**
* \brief Next AltSetting for the Interface
*
* This method returns a pointer to the next AltSetting
* for the Interface.
*
* If you want to iterate through each AltSetting on
* a device, you can use something like the following:
* \code
* USB::Configuration *this_Configuration;
* this_Configuration = device->firstConfiguration();
* for (i=0; i < device->numConfigurations(); i++) {
* this_Configuration->dumpDescriptor();
* USB::Interface *this_Interface;
* this_Interface = this_Configuration->firstInterface();
* for (j=0; j < this_Configuration->numInterfaces(); j++) {
* USB::AltSetting *this_AltSetting;
* this_AltSetting = this_Interface->firstAltSetting();
* for (k=0; k < this_Interface->numAltSettings(); k++) {
* // do something with this_AltSetting
* this_AltSetting = this_Interface->nextAltSetting();
* }
* this_Interface = this_Configuration->nextInterface();
* }
* this_Configuration = device->nextConfiguration();
* }
* \endcode
*
* \see firstAltSetting(), lastAltSetting(), numAltSettings()
*/
AltSetting *nextAltSetting(void);
/**
* \brief Last AltSetting for the Interface
*
* This method returns a pointer to the last AltSetting
* for the Interface.
*
* \see firstAltSetting(), nextAltSetting(), numAltSettings()
*/
AltSetting *lastAltSetting(void);
private:
std::list<AltSetting *>::const_iterator iter;
void setNumAltSettings(u_int8_t);
void setParent(Device *parent);
u_int8_t m_numAltSettings;
Device *m_parent;
/* index representing the interface, in this configuration */
int m_interfaceNumber;
void setInterfaceNumber(int interfaceNumber);
};
/**
* \brief Class representing a configuration of a Device
*
* The Configuration class represents a single configuration
* of a device attached to a Universal Serial Bus.
*
* \author Brad Hards
*/
class Configuration : public std::list<Interface *> {
/**
* Busses is a friend because it fills in the descriptor type
* information on initialisation and rescan.
*/
friend class Busses;
public:
Configuration() {};
/**
* \brief Configuration descriptor information output
*
* This method dumps out the various characteristics
* of the configuration to standard output.
*
* It is mostly useful for debugging.
*/
void dumpDescriptor(void);
/**
* \brief Number of Interfaces that this device has
*
* This is a simple accessor method that specifies the number
* Interfaces that this device configuration has.
*/
u_int8_t numInterfaces(void);
/**
* \brief First Interface for the Configuration
*
* This method returns a pointer to the first Interface
* for the Configuration.
*
* See nextInterface() for an example of how it might be
* used.
*
* \see nextInterface(), lastInterface(), numInterfaces()
*/
Interface *firstInterface(void);
/**
* \brief Next Interface for the Configuration
*
* This method returns a pointer to the next Interface
* for the Configuration.
*
* If you want to iterate through each Interface on
* a device, you can use something like the following:
* \code
* USB::Configuration *this_Configuration;
* this_Configuration = device->firstConfiguration();
* for (i=0; i < device->numConfigurations(); i++) {
* this_Interface = this_Configuration->firstInterface();
* for (j=0; j < this_Configuration->numInterfaces(); j++) {
* // do something with this_Interface
* this_Interface = this_Configuration->nextInterface();
* }
* this_Configuration->nextConfiguration();
* }
* \endcode
*
* \see firstInterface(), lastInterface(), numInterfaces()
*/
Interface *nextInterface(void);
/**
* \brief Last Interface for the Configuration
*
* This method returns a pointer to the last Interface
* for the Configuration.
*
* \see firstInterface(), nextInterface(), numInterfaces()
*/
Interface *lastInterface(void);
private:
std::list<Interface *>::const_iterator iter;
void setDescriptor(struct usb_config_descriptor);
/* we don't use a normal usb_config_descriptor */
/* because that would bring in the interface list */
u_int8_t m_Length;
u_int8_t m_DescriptorType;
u_int16_t m_TotalLength;
u_int8_t m_NumInterfaces;
u_int8_t m_ConfigurationValue;
u_int8_t m_Configuration;
u_int8_t m_Attributes;
u_int8_t m_MaxPower;
};
/**
* \brief Class representing a Device on the Bus
*
* The Device class represents a single device
* attached to a Universal Serial Bus.
*
* \author Brad Hards
*/
class Device : public std::list<Configuration *> {
/**
* Busses is a friend because it fills in the descriptor type
* information on initialisation and rescan.
*/
friend class Busses;
/**
* Interface is a friend because it needs the handle() function to
* perform claim(), release().
*/
friend class Interface;
/**
* Endpoint is a friend because it needs the handle() function to
* perform reads, writes, and other transactions.
*/
friend class Endpoint;
public:
Device() {};
~Device();
/**
* \brief OS representation of filename for this device
*
* libusb++ provides a uniform way of accessing USB
* devices irrespective of the underlying Operation System
* representation. If you want to map the libusb++ representation
* to the Operating System representation, you can do this
* with filename().
*
* On Linux, the filename is usually something like 002, which
* represents the second device (usually the first real device,
* after the root hub pseudo-device) on the bus.
*
* \see Bus::directoryName()
*/
std::string fileName(void);
/**
* \brief The vendor ID number, as provided by the device.
*
* This method returns a number containing the vendor
* (manufacturer) identification number. These are allocated
* by the USB Implementers Forum, and you can construct a
* lookup based on the number to get the manufacturer's name,
* even if the device does not contain a vendor string.
*
* \see Vendor()
*/
u_int16_t idVendor(void);
/**
* \brief The product ID number, as provided by the device.
*
* This method returns a number containing the product
* identification number. These are allocated
* by the manufacturer, and should be different on each device.
*
* \see Product()
*/
u_int16_t idProduct(void);
/**
* \brief The product's revision ID, as provided by the device.
*
* This method returns a number containing the product's revision.
* This revision level is nominally binary coded decimal, but
* hexadecimal revision levels are not uncommon. The binary coded
* decimal version nominally has a major version in the high byte,
* and a minor version in the low byte.
*/
u_int16_t idRevision(void);
/**
* \brief The device's USB class, as provided by the device.
*
* This method returns a number containing the device's class.
* These are defined by the USB Implementer's Forum.
*
* A code of Zero is special (and common) - it means that the
* class is found in the Interface descriptor, rather than in the
* Device descriptor.
*
* A code of 0xFF is also special (and far too common) - it means
* that the manufacturer didn't conform to one of the defined
* class specifications, and chose to implement a vendor specified
* protocol.
*
*/
u_int8_t devClass(void);
/**
* \brief The device's USB subclass, as provided by the device.
*
* This method returns a number containing the device's subclass.
* These subclasses are defined by the USB Implementer's Forum,
* and only have meaning in the context of a specified class.
*/
u_int8_t devSubClass(void);
/**
* \brief The device's USB protocol, as provided by the device.
*
* This method returns a number containing the device's protocol.
* These protocols are defined by the USB Implementer's Forum, and
* only have meaning in the context of a specified class and
* subclass.
*/
u_int8_t devProtocol(void);
/**
* \brief The vendor name string, as provided by the device.
*
* This method returns a string containing the name of the
* device's vendor (manufacturer), as encoded into the device.
*
* Note that not all devices contain a vendor name, and also
* that under some operating systems you may not be able to
* read the vendor name without elevated privledges (typically
* root privledges).
*
* \see idVendor()
**/
std::string Vendor(void);
/**
* \brief The product name string, as provided by the device.
*
* This method returns a string containing the name of the
* device's product name, as encoded into the device.
*
* Note that not all devices contain a product name, and also
* that under some operating systems you may not be able to
* read the vendor name without elevated privledges (typically
* root privledges).
*
* \see idProduct()
**/
std::string Product(void);
/**
* \brief The serial number string, as provided by the device.
*
* This method returns a string containing a serial number for
* the device, as encoded into the device.
*
* Note that few devices contain a serial number string, and also
* that under some operating systems you may not be able to
* read the serial number without elevated privledges (typically
* root privledges). The USB specification requires that serial
* numbers are unique if they are provided, but adherence to this
* requirement by manufacturers is not universal.
**/
std::string SerialNumber(void);
/**
* \brief Number of Configurations that this device has
*
* This is a simple accessor method that specifies the number
* configurations that this device has.
*/
u_int8_t numConfigurations(void);
/**
* \brief fetch an arbitrary string from the device
*
* \param string the string from the device. You can typically
* pass in an empty string for this.
* \param index the index of the string required
* \param lang the language ID to use. Defaults to using the
* first language ID.
*
* \return length of string, or 0 on error.
*/
int string(std::string &buf, int index, u_int16_t lang=0);
/**
* \brief First Configuration for the Device
*
* This method returns a pointer to the first Configuration
* for the Device.
*
* See nextConfiguration() for an example of how it might be
* used.
*/
Configuration *firstConfiguration(void);
/**
* \brief Next Configuration for the Device
*
* This method returns a pointer to the next Configuration
* for the Device.
*
* If you want to iterate through each Configuration on
* a device, you can use something like the following:
* \code
* USB::Configuration *this_Configuration;
* this_Configuration = device->firstConfiguration();
* for (i=0; i < device->numConfigurations(); i++) {
* // do something with this_Configuration
* this_Configuration->nextConfiguration();
* }
* \endcode
*/
Configuration *nextConfiguration(void);
/**
* \brief Last Configuration for the Device
*
* This method returns a pointer to the last Configuration
* for the Device.
*
*/
Configuration *lastConfiguration(void);
/**
* \brief USB control transfer
*
* This method performs a standard control transfer to the default
* endpoint. See the USB specification for more details on this.
*
* \param requestType corresponds to the bmRequestType field
* in the transfer
* \param request corresponds to the bRequest field in the
* transfer
* \param value corresponds to the wValue field in the transfer
* \param index corresponds to the wIndex field in the transfer
* \param length corresponds to the wLength field in the transfer
* \param payload corresponds to the data phase of a control
* transfer
* \param timeout is the timeout period for the control transfer,
* in milliseconds
*
* \return number of bytes sent or received, or a negative number
* in case of error.
*/
int controlTransfer(u_int8_t requestType, u_int8_t request,
u_int16_t value, u_int16_t index, u_int16_t length,
unsigned char *payload,
int timeout = 100);
#ifdef USE_UNTESTED_LIBUSBPP_METHODS
/**
* \brief USB device reset
*
* This method performs a device reset - see USB Specification
* 9.1 for how this changes the device state to the Default state.
*
* \return 0 on success, or a negative number in case of error.
*/
int reset(void);
/**
* \brief Set device configuration
*
* This method sets the device to a particular Configuration.
*
* \param configurationNumber the configuration that the device
* should be changed to.
*
* \return 0 on success, or a negative number in case of error.
*/
int setConfiguration(int configurationNumber);
#endif /* USE_UNTESTED_LIBUSBPP_METHODS */
private:
std::list<Configuration *>::const_iterator iter;
struct usb_dev_handle *handle();
void setFileName(std::string);
void setDescriptor(struct usb_device_descriptor);
void setVendor(std::string);
void setProduct(std::string);
void setSerialNumber(std::string);
void setDevHandle(struct usb_dev_handle *);
std::string m_fileName;
std::string m_Vendor;
std::string m_Product;
std::string m_SerialNumber;
struct usb_device *m_dev;
struct usb_dev_handle *m_handle;
struct usb_device_descriptor m_descriptor;
};
/**
* \brief Class representing a single bus on the machine
*
* This class is essentially a list of Device class instances
*/
class Bus : public std::list<Device *> {
/**
* Busses is a friend because it fills in the directory name
* information on initialisation and rescan.
*/
friend class Busses;
public:
Bus() {};
/**
* \brief OS representation of directory name for this Bus
*
* libusb++ provides a uniform way of accessing USB
* busses irrespective of the underlying Operation System
* representation. If you want to map the libusb++ representation
* to the Operating System representation, you can do this
* with directory name().
*
* On Linux, the directoryname is usually something like 003, which
* represents the third bus on the host.
*
* \see Directory::filename()
*/
std::string directoryName(void);
private:
std::list<Device *>::const_iterator iter;
void setDirectoryName(std::string);
std::string m_directoryName;
};
/**
* \brief A vendor/product ID pair
*
* DeviceID provides a list of (vendor, product) identification
* pairs. It is intended for use in a list of device numbers to
* search for, but there is no reason why it couldn't be used for a
* general purpose (vendor,product) tuple if you had some reason for
* this.
*
* The description for Busses::match() provides an example of how
* this class might be used.
*
* \see DeviceIDList, Busses::match()
*/
class DeviceID {
public:
DeviceID() {};
/**
* \brief Standard constructor
*
* This constructor takes (vendor, product) tuple, which are
* stored away.
*
* \param vendor the 16 bit vendor number for the device
* \param product the 16 bit product number for the device
*/
DeviceID(u_int16_t vendor, u_int16_t product);
/**
* \brief vendor number for the device
*
* This method returns the 16 bit vendor number.
*/
u_int16_t vendor(void);
/**
* \brief product number for the device
*
* This method returns the 16 bit product number.
*/
u_int16_t product(void);
private:
u_int16_t m_vendor;
u_int16_t m_product;
};
/**
* \brief A list of vendor/product pairs
*
* DeviceIDList provides a list of DeviceID classes, which is
* essentially a list of (vendor, product) identification pairs.
*
* \see DeviceID
*/
typedef std::list<DeviceID> DeviceIDList;
/**
* \brief Class representing all the busses on the machine
*
* This class is essentially a list of Bus class instances
*/
class Busses : public std::list<Bus *> {
public:
Busses();
/**
* \brief Update method
*
* This method can be called to rescan the various devices
* attached to the various busses. You should use it to
* update if things change. Unfortunately there is no
* way to automatically detect this change in a portable way,
* so worst case is that you need to call this using some
* kind of timer in the background.
*/
void rescan(void);
/**
* \brief find all devices with matching device class designator
*
* This method searches every device on every bus, and returns a
* list of pointers to the devices that have a matching device
* class code
*/
std::list<Device *> match(u_int8_t Class);
/**
* \brief find all devices with matching device IDs
*
* This method searches every device on every bus, and returns a
* list of pointers to the devices that have a matching device
* ID. That is, if the (vendor, product) tuple of a device matches
* one of the tuples on the list, then the device will be added to
* the list of matches.
*
* An example of usage is shown below:
* \code
* USB::Busses buslist;
* USB::Device *device;
* std::list<USB::Device> miceFound;
* USB::DeviceIDList mouseList;
*
* mouseList.append(USB::DeviceID(VENDOR_LOGITECH, 0xC00E)); // Wheel Mouse Optical
* mouseList.append(USB::DeviceID(VENDOR_LOGITECH, 0xC012)); // MouseMan Dual Optical
* mouseList.append(USB::DeviceID(VENDOR_LOGITECH, 0xC506)); // MX700 Optical Mouse
*
* miceFound = buslist.match(mouseList);
*
* for ( device = miceFound.first(); device; device = miceFound.next() ) {
* // do something with each mouse that matched
* }
* FIXME: This is incorrect now
* \endcode
*/
std::list<Device *> match(DeviceIDList);
private:
std::list<Bus *>::const_iterator iter;
};
class Error {
public:
private:
};
}
#endif /* __USBPP_HEADER__ */
+8
View File
@@ -0,0 +1,8 @@
OBJ=logotool.o compress.o uncompress.o rgb2yuv.o
CFLAGS=-Wall -g
all: ${OBJ}
${CC} ${OBJ} -o logotool
clean:
rm -f ${OBJ} logotool
+17
View File
@@ -0,0 +1,17 @@
Compressing/Uncompressing images
================================
To compress your image type:
$ gimp -> create an image and save as raw rgb (24 bits)
$ logotool -w 300 -h 200 -c MyImage.rgb
This command will create MyImage.rgb.logo
You can check if the image is fine typing:
$ logotool -u MyImage.rgb.logo
To see the image you'll need mplayer and type this:
$ `logotool -u MyImage.rgb.logo`
+145
View File
@@ -0,0 +1,145 @@
/*
* logotool - tool to modify logo images with simple compression
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* esteve <esteve@eslack.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
extern int rgba;
int isbe()
{
int a=1; char *b=(char *)&a;
return (int)b[0];
}
void ememcpy(char *dst, char *src)
{
char buffer[4];
memcpy(buffer, src, 4);
dst[0] = buffer[3]; dst[1] = buffer[2];
dst[2] = buffer[1]; dst[3] = buffer[0];
}
int compress_image(char *srcf, char *dstf, int w, int h)
{
char buf[256];
char tmp[256];
int fdout;
FILE *fd;
int i,ret;
fd = fopen(srcf, "rb");
if (fd == NULL) {
printf("Cannot open file '%s' \n", srcf);
return 1;
}
fdout = open( dstf, O_TRUNC | O_CREAT | O_WRONLY , 0660 );
if (fdout == -1) {
printf("Cannot open file '%s' for writing\n", dstf);
return 1;
}
if (isbe()) {
char oop[4];
ememcpy((char *)&oop, (char *)&w);
write(fdout, &oop, 4);
ememcpy((char *)&oop, (char *)&h);
write(fdout, &oop, 4);
} else {
write(fdout, &w, 4);
write(fdout, &h, 4);
}
fseek(fd, 0, SEEK_END);
if (!rgba && ftell(fd)%3) {
fprintf(stderr, "Oops..looks like RGBA..forcing -a\n");
rgba = 1;
}
fseek(fd, 0, SEEK_SET);
#define MAX 3*80
if (rgba) {
for(;;) {
unsigned char c;
ret = fread(&buf, 1, MAX, fd);
if (ret <= 0) break;
c = ret/4;
write(fdout,&c, 1);
for(i=0;i<ret;i+=4) {
tmp[0] = buf[i+0]&0xf8;
tmp[0] |= buf[i+1]&0x07;
tmp[1] = buf[i+1]&0xe0;
tmp[1] |= buf[i+2]&0x1f;
write(fdout, tmp, 2);
}
}
} else {
for(;;) {
unsigned char c;
ret = fread(buf, 1, MAX, fd);
if (ret <= 0) break;
c = ret/3;
write(fdout,&c, 1);
for(i=0;i<ret;i+=3) {
tmp[0] = buf[i+0]&0xf8;
tmp[0] |= buf[i+1]&0x07;
tmp[1] = buf[i+1]&0xe0;
tmp[1] |= buf[i+2]&0x1f;
write(fdout, tmp, 2);
}
}
}
fclose(fd);
close(fdout);
printf("eval PATH=$PWD:$PATH logotool -u %s\n", dstf);
return 1;
}
#if 0
// TODO: compression stuff
/* is a repeated block? */
c = buf[0];
for(i=1;i<MAX&&buf[i]==c&&buf[i+1]==c;i+=2);
printf("memcpy %d -> %d (ret %d)\n",i,ret-i, ret);
for(i=0;i<ret-i;i++)
printf(" %02x ", (unsigned char)buf[i]);
printf("\n");
if (i>5) {
// if (i==MAX) {
if (0x80>ret) printf("PRON\n");
c = 0x80 | ret; //(int)((2*ret/3)>>1);
write(fdout,&c, 1);
tmp[0] = buf[i+0]&0xf8;
tmp[0] |= buf[i+1]&0x07;
tmp[1] = buf[i+1]&0xe0;
tmp[1] |= buf[i+1]&0x1f;
write(fdout, tmp, 2);
// restore state
memcpy(buf,buf+i,ret-i);
ret -= i;
}
#endif
+130
View File
@@ -0,0 +1,130 @@
/*
* logotool - tool to modify logo images with simple compression
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* esteve <esteve@eslack.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define VERSION "0.1"
int uncompress_image(char *srcf, char *dstf);
int compress_image(char *srcf, char *dstf, int w, int h);
int rgb2yuv(char *from, char *to, int width, int height);
int rgba = 0;
static int show_usage()
{
printf("Usage: logotool [-flags]\n");
printf(" -u [img] uncompress image to img.rgb\n");
printf(" -c [img] compres a 24 bit rgb raw image to a 16(565) one\n");
printf(" -m [img] show image using mplayer (dumps to <img>.yuv)\n");
printf(" -v [img] view uncompressed image using the 'display'\n");
printf(" command from ImageMagick (in monochrome)\n");
printf(" -w specify width (required for -v and -c)\n");
printf(" -a force RGBA instead of RGB when compressing (use with -c)\n");
printf(" -h specify height (required for -v and -c)\n");
printf(" -V version number\n");
printf("\n");
printf("Example:\n");
printf(" $ `logotool -u logo-file` # uncompress and display a logo\n");
return 1;
}
int main ( int argc , char** argv )
{
int c;
int w=0,h=0;
char *mimg = NULL;
char *cimg = NULL;
char *uimg = NULL;
char *view = NULL;
while((c = getopt(argc, argv, "w:h:Vv:u:c:m:a")) != -1) {
switch(c) {
case 'V': printf("%s\n", VERSION); return 0;
case 'u': uimg = optarg; break;
case 'c': cimg = optarg; break;
case 'm': mimg = optarg; break;
case 'a': rgba = 1; break;
case 'w': w = atoi(optarg); break;
case 'h': h = atoi(optarg); break;
case 'v': view = optarg; break;
}
}
if (mimg) {
char *buf;
if (w==0||h==0) {
printf("You must specify width and height with '-w' and '-h'.\n");
return 1;
}
buf = (char *)malloc(strlen(mimg)+128);
sprintf(buf, "%s.rgb", mimg);
if ( rgb2yuv(mimg, buf, w,h ) ) {
sprintf(buf, "echo pause | mplayer %s.rgb -slave -demuxer rawvideo -rawvideo fps=1:w=%d:h=%d", mimg, w,h);
system(buf);
} else {
printf("Oops\n");
}
free(buf);
} else
if (view) {
char *buf;
if (w==0||h==0) {
printf("You must specify width and height with '-w' and '-h'.\n");
return 1;
}
buf = (char *)malloc(strlen(view)+128);
sprintf(buf, "display -size %dx%d -depth 16 %s", w,h,view);
printf("%s\n", buf);
system(buf);
free(buf);
} else
if (uimg) {
char *dst = (char*)malloc(strlen(uimg)+5);
strcpy(dst, uimg);
strcat(dst, ".gray");
uncompress_image(uimg, dst);
free(dst);
} else
if (cimg) {
char *dst;
if (w==0||h==0) {
printf("You must specify width and height with '-w' and '-h'.\n");
return 1;
}
dst = (char*)malloc(strlen(cimg)+6);
strcpy(dst, cimg);
strcat(dst, ".logo");
compress_image(cimg, dst, w, h);
free(dst);
} else
show_usage();
return 0;
}
+111
View File
@@ -0,0 +1,111 @@
/*
* logotool - tool to modify logo images with simple compression
* Copyright (C) 2007
* esteve <esteve@eslack.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void RGBtoYUV(unsigned short in565, unsigned char *yuv)
{
/* 2 bytes, 565
* RRRRR GGGGGG BBBBB
*/
int i;
i = (in565>>8)&0xFF;
in565 = (in565<<8)&0xFF00;
in565 |= i;
int rgb[3];
rgb[0] = (in565>>11)&0x1F;
rgb[1] = (in565>>5)&0x3F;
rgb[2] = (in565)&0x1F;
rgb[0] = (rgb[0]<<3) | 0x7;
rgb[1] = (rgb[1]<<2) | 0x3;
rgb[2] = (rgb[2]<<3) | 0x7;
/*yuv[0] = 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
yuv[1] = (rgb[2]-yuv[0])*0.565 + 128;
yuv[2] = (rgb[0]-yuv[0])*0.713 + 128;*/
yuv[0] = (0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16;
yuv[1] = 128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2]);
yuv[2] = 128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2]);
}
// mplayer caca.yuv -demuxer rawvideo -rawvideo fps=1:w=416:h=70 //:i420
int rgb2yuv(char *from, char *to, int width, int height)
{
int fd=open (from, O_RDONLY );
int fout= open ( to, O_CREAT| O_WRONLY , 0660 );
int fsize;
unsigned char* src;
unsigned char* dstY;
unsigned char* dstU;
unsigned char* dstV;
unsigned char YUV[3];
unsigned short inP;
int i,j;
if (fd == -1) {
printf("cannot open %s\n", from);
return 0;
}
if (fout == -1) {
printf("cannot open %s\n", to);
return 0;
}
fsize = lseek ( fd, 0,SEEK_END);
fsize = lseek ( fd, 0,SEEK_CUR);
lseek ( fd,0, SEEK_SET);
src=malloc ( fsize );
dstY=malloc ( (fsize/2) );
dstU=malloc ( (fsize/2) );
dstV=malloc ( (fsize/2) );
for ( i = 0 ; i < fsize; i+=2 ) {
read ( fd, &inP, 2 );
RGBtoYUV ( inP, YUV );
dstY[i>>1]=YUV[0];
dstU[i>>1]=YUV[1];
dstV[i>>1]=YUV[2];
}
for ( i = 0 ; i < (fsize/2); i++ )
write ( fout,&dstY[i], 1);
for ( i = 0 ; i < height ; i+=2 )
for ( j = 0; j < width ; j +=2 )
write ( fout,&dstU[j+(i*width)], 1);
for ( i = 0 ; i < height ; i+=2 )
for ( j = 0; j < width ; j +=2 )
write ( fout,&dstV[j+(i*width)], 1);
return 1;
}
+123
View File
@@ -0,0 +1,123 @@
/*
* logotool - tool to modify logo images with simple compression
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* esteve <esteve@eslack.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int uncompress_image(char *srcf, char *dstf)
{
int fd;
int fout;
int width,height;
int fsize;
char* src;
char* dst;
char* src2;
char* eof;
char *deof;
char* dst2 = NULL;
unsigned char byte;
fd = open( srcf, O_RDONLY );
if (fd == -1) {
printf("Cannot open file '%s'\n", srcf);
return 1;
}
fout = open( dstf, O_CREAT | O_WRONLY , 0660 );
if (fout == -1) {
printf("Cannot open file '%s' for writing\n", dstf);
return 1;
}
fprintf(stderr, "Input file: %s\n", srcf);
fprintf(stderr, "Output file: %s\n", dstf);
fsize = lseek ( fd, 0,SEEK_END);
fsize = lseek ( fd, 0,SEEK_CUR);
lseek ( fd,0, SEEK_SET);
fsize -= 8;
read ( fd, &width, 4 );
read ( fd, &height, 4 );
fprintf(stderr, "Width: %d\nHeight: %d\n",width, height);
fprintf(stderr, "Input Size: %d\n",fsize);
src = malloc ( fsize );
dst = malloc ( width*height*2 );
deof = dst+width*height*2;
if ((int)src == -1 || (int)dst == -1 ) {
printf("Cannot malloc\n");
return 1;
}
memset(dst,'\0', width*height*2);
read(fd, src, fsize);
eof = src+fsize;
for(dst2 = dst, src2 = src; src2<eof;) {
//byte = src2[0] & 0xff;
//src2 = src2 + 1;
byte=(*src2++)&0xff;
// [1xxxyyyy] [char] [char]
// copies xxxyyyy times two chars
if (byte > 0x7f) {
int i,j = byte&0x7f;
for(i=0; i++<j; dst2+=2)
memcpy(dst2, src2, 2);
src2+=2;
} else {
if ( byte != 0x00 ) {
byte<<=1;
// fprintf(stderr, "COPYING: %d %d\n", byte, (eof-src2));
if ((dst2+byte >= deof || (src2+byte >= eof))) {
fprintf(stderr, "Break\n");
break;
}
memcpy(dst2, src2, byte);
src2+=byte; dst2+=byte;
}
}
}
fprintf(stderr, "Output Size: %d\n",dst2-dst);
if ((dst2-dst)!=(width*height*2))
fprintf(stderr, "failed?\n");
write ( fout, dst, width*height*2);
close(fout);
close(fd);
//printf("./logotool -w %d -h %d -v %s || \n", width, height, dstf);
//printf("logotool -w %d -h %d -v %s\n", width, height, dstf);
printf("eval PATH=$PWD:$PATH logotool -w %d -h %d -m %s\n", width, height, dstf);
return 0;
}
+13 -5
View File
@@ -1,11 +1,19 @@
VERSION=0.1
OBJ=main.o fiasco.o hexdump.o dump.o flash.o
OBJ+=hash.o fpid.o query.o pieces.o utils.o
VERSION=0.3
OBJ=main.o fiasco.o hexdump.o dump.o flash.o serial.o
OBJ+=hash.o fpid.o query.o pieces.o utils.o devices.o console.o
BIN=0xFFFF
CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -g
CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -g -I .
USBOBJ=../libusb/error.o ../libusb/usb.o ../libusb/descriptors.o
USBOBJ+=../libusb/linux.o ## XXX not portable
main: ${OBJ}
all: ${OBJ}
${CC} ${LDFLAGS} -o ${BIN} ${OBJ} -lusb
allusb: ${OBJ}
${CC} ${LDFLAGS} -o ${BIN} ${OBJ} ${USBOBJ}
static: ${OBJ}
${CC} ${LDFLAGS} -o ${BIN} -static ${OBJ} ${USBOBJ}
clean:
-rm -f ${OBJ} ${BIN}
+163
View File
@@ -0,0 +1,163 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include "query.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
void cmd_exit(char *line)
{
exit(0);
}
void cmd_help(char *line)
{
printf("connect connects via usb to nolo\n");
printf("reboot reboots remote host\n");
printf("info shows info of the remote system\n");
printf("linfo shows info of the local system\n");
printf("shell opens a shell (/bin/sh)\n");
printf("badblocks [dev] checks bad blocks on mtd (/dev/mtd1)\n");
printf("dump [dir] dumps the contents of /dev/mtd to dir\n");
printf("nanddump [dev] [start] [len] [out] [ignore-badblocks] [ignore-oob]\n");
printf(" f.ex: nanddump /dev/mtd0 0x0 0x4000 xloader.bin 1 1\n");
printf("exit exits the shell\n");
fflush(stdout);
}
void cmd_info(char *line)
{
get_hw_revision(); // get hardware revision:
get_root_device(); // only for flashing
get_usb_mode();
get_rd_mode();
get_rd_flags();
}
void cmd_nanddump(char *line)
{
char dev[128];
int from;
int length;
char out[128];
int ignbb;
int ignoob = -1;
sscanf(line, "%127s 0x%x 0x%x %127s %d %d", &dev, &from, &length, &out, &ignbb, &ignoob);
if (ignoob == -1) {
printf("Invalid arguments.\n");
printf("nanddump [dev] [start] [len] [out] [ignore-badblocks] [ignore-oob]\n");
printf(" f.ex: nanddump /dev/mtd0 0x0 0x4000 xloader.bin 1 1\n");
} else {
nanddump(dev, from, length, out, ignbb, ignoob);
}
}
void cmd_dump(char *line)
{
if (!line[0]) {
printf("Usage: dump [path]\n");
return;
}
while(line[0]==' ') line = line +1;
reverse_extract_pieces(line);
}
void cmd_badblocks(char *line)
{
if (!line[0]) {
printf("Usage: dump [path]\n");
return;
}
while(line[0]==' ') line = line +1;
check_badblocks(line);
}
void cmd_connect(char *line)
{
connect_via_usb();
}
void cmd_reboot(char *line)
{
reboot_board();
}
void cmd_shell(char *line)
{
system("/bin/sh");
}
#define CMDS 11
#define IS_CMD(x) !strcmp(console_commands[i].name, x)
#define CALL_CMD(x) console_commands[x].callback((char *)line)
#define FOREACH_CMD(x) for(x=0;x<CMDS;x++)
struct cmd_t {
char *name;
void (*callback)(char *);
} console_commands[CMDS] = {
{ .name = "exit", .callback = &cmd_exit },
{ .name = "q", .callback = &cmd_exit },
{ .name = "connect", .callback = &cmd_connect },
{ .name = "reboot", .callback = &cmd_reboot },
{ .name = "badblocks", .callback = &cmd_badblocks},
{ .name = "help", .callback = &cmd_help },
{ .name = "?", .callback = &cmd_help },
{ .name = "info", .callback = &cmd_info },
{ .name = "dump", .callback = &cmd_dump },
{ .name = "nanddump", .callback = &cmd_nanddump },
{ .name = "shell", .callback = &cmd_shell }
};
static int console_command(const char *line)
{
int i;
char command[11];
command[0] = '\0';
sscanf(line, "%10s", command);
line = line + strlen(command);
FOREACH_CMD(i)
if (IS_CMD(command))
CALL_CMD(i);
//
return 1;
}
int console_prompt()
{
char line[1024];
do {
write(1, "0xFFFF> ", 8);
line[0] = '\0';
fgets(line, 1024, stdin);
if (feof(stdin)) {
write(1, "\n", 1);
break;
}
if (line[0]) line[strlen(line)-1] = '\0';
line[1023] = '\0';
} while(console_command(line));
return 0;
}
+118
View File
@@ -0,0 +1,118 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* The internet tablet PC (and probably most of
* Nokia devices have different USB-IDs depending
* on the boot state.
*
* The following table shows this info:
*
* boot os
* n770 0421:0105 0421:0431
* n800 0421:0431
*
*/
struct devices supported_devices[SUPPORTED_DEVICES] = {
{ "FFFF", 0x000, 0x0000, 0x0000 }, // dummy
{ "unkn", 0x421, 0x3f00, 0x0000 }, // probably a development board
{ "n770", 0x421, 0x0105, 0x0001 }, // my n770
{ "n800", 0x421, 0x04c3, 0x0001 }, // a n800
{ 0 },
{ 0 }
};
/** Returns 0 when no device was found and a positive
* non-zero value when one was found.
*
* The return value is the index into the supported_devices
* array which denotes the device which was found.
*/
int is_valid_device(struct usb_device_descriptor *udd)
{
int i;
struct devices ptr = supported_devices[1];
for(i=1 ; ptr.vendor_id; ptr = supported_devices[++i])
if ((udd->idVendor == ptr.vendor_id)
&& (udd->idProduct == ptr.product_id)) {
D printf("found %s\n", supported_devices[i]);
return i;
}
return 0;
}
/*
* List all supported device-ids and it's names
*
*/
void list_valid_devices()
{
int i;
struct devices ptr = supported_devices[1];
for(i=1; ptr.vendor_id; ptr = supported_devices[++i])
printf("%04x:%04x %s\n", ptr.vendor_id, ptr.product_id, ptr.name);
}
/*
* Returns true (1) when a valid usb device is found and stores the udd and devices
* structures for the specified device.
* Otherwise returns false (0)
*/
int usb_device_found(struct usb_device_descriptor *udd, struct devices *it_device)
{
struct usb_bus *bus;
int dev_index = 0;
if (usb_find_busses() < 0) {
fprintf(stderr, "\nerror: no usb busses found.\n");
exit(1);
} else {
switch(usb_find_devices()) {
case -1:
fprintf(stderr, "\nerror: no devices found.\n");
exit(1);
default:
for (bus = usb_busses; bus; bus = bus->next) {
struct usb_device *dev = bus->devices;
D printf("bus: \n");
for (; dev; dev = dev->next) {
*udd = dev->descriptor;
D printf(" dev (%s) - ", dev->filename);
D printf("vendor: %04x product: %04x\n", udd->idVendor, udd->idProduct);
if ((dev_index = is_valid_device(udd))) {
device = dev;
*it_device = supported_devices[dev_index];
return 1;
}
}
}
}
}
return 0;
}
+478 -43
View File
@@ -1,29 +1,35 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include "hexdump.h"
#include <usb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Extracts a piece from an mtd device
* -----------------------------------
* This function is known to be buggy, It does not takes care about
* badblocks and oob data. It is replaced by nanddump(), but will
* probably be fixed in the future or it will die.
*/
int rf_extract(char *dev, off_t from, off_t to, char *file)
{
off_t i, blk = 0xfffff;
@@ -38,15 +44,15 @@ int rf_extract(char *dev, off_t from, off_t to, char *file)
if (fs == NULL) { perror(dev); goto __rf_extract_exit; }
if (fd == NULL) { perror(file); goto __rf_extract_exit; }
printf("%s: extracting...", file);
fflush(stdout);
printf("Extracting %s...\n", file);
fseek(fs, from, SEEK_SET);
for(i=from;i<to;i+=blk) {
int ret;
if (i+blk>to) blk = to-i;
ret = fread(buf, blk, 1, fs);
if (feof(fs)) break;
progressbar(i, to);
if (!ret || feof(fs)) break;
fwrite(buf, blk, 1, fd);
}
@@ -57,7 +63,353 @@ __rf_extract_exit:
if (fs) fclose(fs);
if (fd) fclose(fd);
return 1;
}
/*
* This function was covardly copied from nanddump.c @ mtd-utils-20060907
*/
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <mtd/mtd-user.h>
#define M_RDONLY 0x00000001
#define M_RDRW 0x00000002
#define M_OMITOOB 0x00000010
#define M_OMITBAD 0x00000011
#define M_OMITECC 0x00000012
int mtd_open(char *file, mtd_info_t *meminfo, int *oobinfochanged,
struct nand_oobinfo *old_oobinfo, int *eccstats, int flags)
{
int fd;
*oobinfochanged = 0 ;
fd = open(file, (flags&M_RDONLY)?O_RDONLY:O_RDWR);
if (fd == -1) {
perror("mtd_open");
return -1;
}
/* Fill in MTD device capability structure */
if (ioctl(fd, MEMGETINFO, meminfo) != 0) {
perror("MEMGETINFO");
close(fd);
return 1;
}
/* Make sure device page sizes are valid */
if (!(meminfo->oobsize == 64 && meminfo->writesize == 2048) &&
!(meminfo->oobsize == 16 && meminfo->writesize == 512) &&
!(meminfo->oobsize == 8 && meminfo->writesize == 256)) {
fprintf(stderr, "Unknown flash (not normal NAND)\n");
close(fd);
return -1;
}
return fd;
}
int mtd_close(int fd, struct nand_oobinfo *old_oobinfo, int oobinfochanged)
{
if (fd == -1)
return 1;
/* reset oobinfo */
if (oobinfochanged == 1) {
if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
perror ("MEMSETOOBSEL");
close(fd);
return 1;
}
}
/* Close the output file and MTD device */
return close(fd);
}
// configuration for nanddump //
//int noecc = 0; // don't error correct
int omitoob = 1; // omit oob data
int omitbad = 1;
// configuration for nanddump //
#define CONFIGURE_FLAGS(x) \
omitoob = x & M_OMITOOB; \
omitbad = x & M_OMITBAD;
int check_badblocks(char *mtddev)
{
int fd;
int oobinfochanged = 0 ;
int badblock = 0;
int badblocks = 1;
int eccstats = 0;
unsigned long int i;
unsigned long long blockstart = 1;
unsigned char oobbuf[64];
struct nand_oobinfo old_oobinfo;
struct mtd_oob_buf oob = {0, 16, oobbuf};
struct mtd_ecc_stats stat1, stat2;
mtd_info_t meminfo;
fd = mtd_open(mtddev, &meminfo, &oobinfochanged, &old_oobinfo, &eccstats, M_RDONLY);
if (fd == -1) {
printf("cannot open mtd\n");
return 1;
}
fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
fprintf(stderr, "Size %u, flags %u, type 0x%x\n",
meminfo.size, meminfo.flags, (int)meminfo.type);
oob.length = meminfo.oobsize;
for(i = 0; i < meminfo.size; i+= meminfo.writesize) {
// new eraseblock , check for bad block
if (blockstart != (i & (~meminfo.erasesize + 1))) {
blockstart = i & (~meminfo.erasesize + 1);
if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
perror("ioctl(MEMGETBADBLOCK)");
goto closeall;
}
}
if (badblock) {
if (omitbad) {
printf("Bad block found at 0x%lx\n", i);
continue;
}
} else {
char readbuf[2048]; // XXX hardcoded like mtd-utils?? ugly!
// dummy -- should be removed
if (pread(fd, readbuf, meminfo.writesize, i) != meminfo.writesize) {
perror("pread");
goto closeall;
}
}
/* ECC stats available ? */
if (eccstats) {
if (ioctl(fd, ECCGETSTATS, &stat2)) {
perror("ioctl(ECCGETSTATS)");
goto closeall;
}
if (stat1.failed != stat2.failed)
fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
" at offset 0x%08lx\n",
stat2.failed - stat1.failed, i);
if (stat1.corrected != stat2.corrected)
fprintf(stderr, "ECC: %d corrected bitflip(s) at"
" offset 0x%08lx\n",
stat2.corrected - stat1.corrected, i);
stat1 = stat2;
}
if (badblock) {
printf("Oops badblock %d at 0x%lx !\n", badblocks++, i);
} else {
/* Read OOB data and exit on failure */
oob.start = i;
if (ioctl(fd, MEMREADOOB, &oob) != 0) {
perror("ioctl(MEMREADOOB)");
goto closeall;
}
}
/* Write out OOB data */
if (badblock)
D dump_bytes(oobbuf, meminfo.oobsize);
}
mtd_close(fd, &old_oobinfo, oobinfochanged);
return 0;
closeall:
mtd_close(fd, &old_oobinfo, oobinfochanged);
return 1;
}
int nanddump(char *mtddev, unsigned long start_addr, unsigned long length, char *dumpfile, int isbl)
{
unsigned char readbuf[2048];
int oobinfochanged = 0 ;
unsigned char oobbuf[64];
unsigned long ofs, end_addr = 0;
unsigned long long blockstart = 1;
struct nand_oobinfo none_oobinfo = {
.useecc = MTD_NANDECC_OFF,
};
int fd, ofd, bs, badblock = 0;
struct mtd_oob_buf oob = {0, 16, oobbuf};
mtd_info_t meminfo;
int badblocks = 1;
struct nand_oobinfo old_oobinfo;
int eccstats = 0;
struct mtd_ecc_stats stat1, stat2;
int flags = M_RDONLY;
printf("\nExtracting %s from %s...\n", dumpfile, mtddev);
fd = mtd_open(mtddev, &meminfo, &oobinfochanged, &old_oobinfo, &eccstats, flags);
if (meminfo.writesize == 0) {
printf("What the fuck.. this is not an MTD device!\n");
close(fd);
return 1;
}
/* Read the real oob length */
oob.length = meminfo.oobsize;
fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
fprintf(stderr, "Size %u, flags %u, type 0x%x\n",
meminfo.size, meminfo.flags, (int)meminfo.type);
if (flags & M_OMITECC) { // (noecc)
switch (ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW)) {
case -ENOTTY:
if (ioctl (fd, MEMGETOOBSEL, old_oobinfo) != 0) {
perror ("MEMGETOOBSEL");
close (fd);
exit (1);
}
if (ioctl (fd, MEMSETOOBSEL, none_oobinfo) != 0) {
perror ("MEMSETOOBSEL");
close (fd);
exit (1);
}
oobinfochanged = 1;
break;
case 0:
oobinfochanged = 2;
break;
default:
perror ("MTDFILEMODE");
close (fd);
return 1;
}
} else {
/* check if we can read ecc stats */
if (!ioctl(fd, ECCGETSTATS, &stat1)) {
eccstats = 1;
fprintf(stderr, "ECC failed: %d\n", stat1.failed);
fprintf(stderr, "ECC corrected: %d\n", stat1.corrected);
fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks);
fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks);
} else
perror("No ECC status information available");
}
/* Open output file for writing. If file name is "-", write to standard
* output. */
if (!dumpfile) {
ofd = STDOUT_FILENO;
} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) {
perror ("open outfile");
close(fd);
return 1;
}
/* Initialize start/end addresses and block size */
if (length)
end_addr = start_addr + length;
if (!length || end_addr > meminfo.size)
end_addr = meminfo.size;
bs = meminfo.writesize;
fprintf(stderr,
"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
(unsigned int) start_addr, (unsigned int) end_addr);
/* Dump the flash contents */
for (ofs = start_addr; ofs < end_addr ; ofs+=bs) {
// new eraseblock , check for bad block
if (blockstart != (ofs & (~meminfo.erasesize + 1))) {
blockstart = ofs & (~meminfo.erasesize + 1);
if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
perror("ioctl(MEMGETBADBLOCK)");
goto closeall;
}
}
if (!isbl && badblock) {
if (omitbad)
continue;
memset (readbuf, 0xff, bs);
} else {
/* Read page data and exit on failure */
if (pread(fd, readbuf, bs, ofs) != bs) {
perror("pread");
goto closeall;
}
}
// TODO exist on n800??? // remove code?
/* ECC stats available ? */
if (eccstats) {
if (ioctl(fd, ECCGETSTATS, &stat2)) {
perror("ioctl(ECCGETSTATS)");
goto closeall;
}
if (stat1.failed != stat2.failed)
fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
" at offset 0x%08lx\n",
stat2.failed - stat1.failed, ofs);
if (stat1.corrected != stat2.corrected)
fprintf(stderr, "ECC: %d corrected bitflip(s) at"
" offset 0x%08lx\n",
stat2.corrected - stat1.corrected, ofs);
stat1 = stat2;
}
/* Write out page data */
//if (pretty_print) dump_bytes(readbuf, bs);
progressbar(ofs, end_addr);
// OOB STUFF //
if (omitoob)
continue;
if (!isbl&&badblock) {
printf("Oops badblock %d *ignored* at 0x%lx !\n", badblocks++, ofs);
memset (readbuf, 0xff, meminfo.oobsize);
} else {
/* Read OOB data and exit on failure */
oob.start = ofs;
if (ioctl(fd, MEMREADOOB, &oob) != 0) {
perror("ioctl(MEMREADOOB)");
goto closeall;
}
}
/* Write out OOB data */
D dump_bytes(oobbuf, meminfo.oobsize);
write(ofd, oobbuf, meminfo.oobsize);
}
mtd_close(fd, &old_oobinfo, oobinfochanged);
close(ofd);
return 0;
closeall:
mtd_close(fd, &old_oobinfo, oobinfochanged);
close(ofd);
return 1;
}
@@ -75,18 +427,19 @@ int rf_strip(char *file)
printf("Stripping padding from %s... ", file);
fflush(stdout);
fseek(fd, 0, SEEK_END);
do {
fseek(fd, -4096, SEEK_CUR);
ret = fread(buf, 1, 4096, fd);
fseek(fd, -4096, SEEK_CUR);
for(ret--;ret>0;ret--)
if (buf[ret]!=0xff) {
fseek(fd, ret+1, SEEK_CUR);
eof = ftell(fd);
goto __done;
}
} while(1);
if (ftell(fd)>4096) {
do {
fseek(fd, -4096, SEEK_CUR);
ret = fread(buf, 1, 4096, fd);
fseek(fd, -4096, SEEK_CUR);
for(ret--;ret>0;ret--)
if (buf[ret]!=0xff) {
fseek(fd, ret+1, SEEK_CUR);
eof = ftell(fd);
goto __done;
}
} while(1);
}
__done:
fclose(fd);
@@ -115,31 +468,113 @@ int is_n800()
return n800;
}
int dump_config()
{
mtd_info_t meminfo;
int fd = open("/dev/mtd1", O_RDONLY);
char buf[1024];
int i=0,j;
int ret;
if (fd == -1) {
perror("open /dev/mtd1");
return 1;
}
if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
perror("MEMGETINFO");
close(fd);
return 1;
}
while(i<0x60000) {
iniloop:
ret = read(fd, buf, 4);
if (ret == -1)
break;
if (!memcmp(buf,"ConF", 4)) {
loop:
read(fd, buf, 4);
if (ret == -1) break;
printf("\n0x%08x : ConF %02x %02x %02x %02x : ", i,
buf[0], buf[1], buf[2], buf[3]);
fflush(stdout);
while(1) {
ret = read(fd, buf, 4);
if (ret <1) {
printf("Unexpected eof\n");
break;
}
if (buf[0]=='\0'||buf[1]=='\0'||buf[2]=='\0'||buf[3]=='\0') {
printf("%s \t ", buf);
fflush(stdout);
while(1) {
ret = read(fd, buf, 4);
if (ret <1) {
printf("Unexpected eof\n");
break;
}
if (!memcmp(buf,"\xff\xff\xff\xff", 4))
goto iniloop;
if (!memcmp(buf,"ConF", 4))
goto loop;
printf ("%02x %02x %02x %02x ",
buf[0], buf[1], buf[2], buf[3]);
}
break;
} else {
write(1, buf,4);
}
}
}
j = lseek(fd, 0, SEEK_CUR);
if (j==i) break; i = j;
}
close(fd);
printf("\n");
return 0;
}
int reverse_extract_pieces(char *dir)
{
char reply;
chdir(dir);
rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin");
rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin");
rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage");
rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2");
printf("\nWARNING: the rootfs extraction on n800 is known to be buggy! feedback is welcome.\n\n");
printf("Extract rootfs? (Y/n): "); fflush(stdout);
// TODO: get values from /proc/mtd ???
//rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin");
nanddump("/dev/mtd0", is_n800()?0x200:0, 0x4000, "xloader.bin", 1); // 0x3600 size?
//rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin");
nanddump("/dev/mtd0", 0x004000, 0, "secondary.bin", 1);
nanddump("/dev/mtd1", 0, 0, "config.bin", 0);
//rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage");
nanddump("/dev/mtd2", 0x000800, 0, "zImage", 0);
//rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2");
nanddump("/dev/mtd3", 0x000000, 0, "initfs.jffs2", 0);
printf("\n\nExtract rootfs? (y/N): "); fflush(stdout);
read(0, &reply, 1);
if (reply=='y'||reply=='Y')
rf_extract("/dev/mtd4", 0x000000, 0xffffff, "rootfs.jffs2");
else printf("*** Ignoring rootfs\n");
rf_strip("xloader.bin");
rf_strip("secondary.bin");
rf_strip("zImage");
rf_strip("initfs.jffs2");
printf("Identifying extracted files...\n");
if (reply=='y'||reply=='Y') {
//rf_extract("/dev/mtd4", 0x000000, 0x6000000, "rootfs.jffs2");
nanddump("/dev/mtd4", 0x000000, 0, "rootfs.jffs2", 0);
} else printf("*** Ignoring rootfs\n");
printf("\n\nStrip dumped files? (y/N): "); fflush(stdout);
read(0, &reply, 1);
if (reply=='y'||reply=='Y') {
rf_strip("xloader.bin");
rf_strip("secondary.bin");
rf_strip("zImage");
rf_strip("initfs.jffs2");
} else printf("*** Ignoring strip\n");
printf("\nIdentifying extracted files...\n");
printf("%s: xloader\n", fpid_file("xloader.bin"));
printf("%s: secondary.bin\n", fpid_file("secondary.bin"));
printf("%s: config.bin\n", fpid_file("config.bin"));
printf("%s: zImage\n", fpid_file("zImage"));
printf("%s: initfs.jffs2\n", fpid_file("initfs.jffs2"));
printf("%s: rootfs.jffs2\n", fpid_file("rootfs.jffs2"));
return 1;
}
+261 -104
View File
@@ -1,136 +1,293 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include "main.h"
#include "hash.h"
#warning The FIASCO format is not yet fully implemented.
void (*fiasco_callback)(struct header_t *header) = NULL;
off_t piece_header_to_size(unsigned char *header)
int openfiasco(char *name)
{
off_t sz = 0;
sz += header[0x15+3];
sz += header[0x15+2] << 8;
sz += header[0x15+1] << 16;
sz += header[0x15+0] << 24;
return sz;
}
struct header_t header;
unsigned char buf[128];
unsigned char data[128];
unsigned int namelen;
off_t off;
int i;
header.fd = open(name, O_RDONLY);
int piece_header_is_valid(unsigned char *header)
{
if (header[0]=='T' && header[1]=='\x02')
if (header.fd == -1) {
fprintf(stderr, "Cannot open %s\n", name);
return 1;
}
/* read header */
read(header.fd, buf, 5);
if (buf[0] != 0xb4) {
printf("Invalid header\n");
return close(header.fd);
}
memcpy(&namelen,buf+1,4);
namelen = ntohl(namelen);
if (namelen>128) {
printf("Stupid length at header. Is this a joke?\n");
return close(header.fd);
}
memset(buf,'\0', 128);
read(header.fd, buf, namelen);
printf("Fiasco version: %2d\n", buf[3]);
strcpy(header.fwname, buf+6);
for(i=6;i<namelen;i+=strlen(buf+i)+1)
printf("Name: %s\n", buf+i);
/* walk the tree */
while(1) {
if (read(header.fd, buf, 9)<9)
break;
if (buf[0] != 0x54) { // 'T'
printf("unexpected header at 0x%x, found %02x %02x %02x\n",
((int)lseek(header.fd, 0, SEEK_CUR))-9,
buf[0], buf[1], buf[2]);
break;
}
header.hash = buf[7]<<8|buf[8];
/* piece name */
memset(data, '\0', 13);
if (read(header.fd, data, 12)<12)
break;
if (data[0] == 0xff) {
printf(" [eof]\n");
break;
} else printf(" %s\n", data);
strcpy(header.name, data);
if (read(header.fd, buf, 9)<9)
break;
memcpy(&header.size, buf,4);
header.size = ntohl(header.size);
printf(" size: %d bytes\n", header.size);
printf(" hash: %04x\n", header.hash);
//printf("BYTE: %02x %02x %02x %02x %02x\n",
// buf[4], buf[5], buf[6], buf[7], buf[8]);
/* XXX this is not ok */
//printf("BUF8: %02x\n", buf[8]);
while (buf[8] && buf[8]>'0' && buf[8] < '9') {
if (read(header.fd, data, 1)<1)
break;
i = data[0];
if (read(header.fd, data, i)<i)
break;
if (data[0])
printf(" version: %s\n", data);
strcpy(header.version, data);
if (read(header.fd, buf+8, 1)<1)
break;
}
/* callback */
off = lseek(header.fd, 0, SEEK_CUR);
if (fiasco_callback != NULL) {
fiasco_callback(&header);
free(header.data);
continue;
}
// XXX dup
lseek(header.fd, off, SEEK_SET);
lseek(header.fd, header.size, SEEK_CUR);
}
return 0;
}
#define piece_header_to_name(x) x+0x9;
void fiasco_data_read(struct header_t *header)
{
header->data = (char *)malloc(header->size);
if (header->data == NULL) {
printf("Cannot alloc %d bytes\n", header->size);
return;
}
read(header->fd, header->data, header->size);
}
/*
* Teh Fiasco firmware parser lives here!
*/
int fiasco_read_image(char *file)
/* fiasco writer */
int fiasco_new(const char *filename, const char *name)
{
int fd;
unsigned char header[5];
unsigned char version[55];
char *version2;
//int len = htonl(strlen(name)+1+6+14);
fd = open(file, O_RDONLY);
printf("WARNING: Fiasco firmware is not yet fully supported. Don't relay on it ATM.\n");
if (fd == -1) {
printf("Cannot open fiasco image.\n");
fd = open(filename, O_RDWR|O_CREAT, 0644);
if (fd == -1)
return -1;
#if 1
write(fd, "\xb4\x00\x00\x00\x14\x00\x00\x00\x01\xe8\x0e", 11);
write(fd, "OSSO UART+USB", 14);
#else
/* 2nd format doesnt works. atm stay with old one */
write(fd, "\xb4", 1);
write(fd, &len, 4);
/* version header */
write(fd, "\x00\x00\x00\x02\xe8\x0e", 6);
/* firmware type */
write(fd, "OSSO UART+USB", 14);
/* firmware name */
write(fd, name, strlen(name));
write(fd, "", 1);
#endif
return fd;
}
int fiasco_add_eof(int fd)
{
#if 0
unsigned char buf[120];
if (fd == -1)
return -1;
memset(buf,'\xff', 120);
write(fd, buf, 120);
#endif
return 0;
}
int fiasco_add(int fd, const char *name, const char *file, const char *version)
{
int gd,ret;
unsigned int sz;
unsigned char len;
unsigned short hash;
unsigned char *ptr = (unsigned char *)&hash;
char buf[4096];
char bname[32];
if (fd == -1)
return -1;
if (file == NULL)
return -1;
gd = open(file, O_RDONLY);
if (gd == -1)
return -1;
sz = htonl((unsigned int) lseek(gd, 0, SEEK_END));
lseek(gd, 0, SEEK_SET);
// 4 bytes big endian
//write(fd, "T\x02\x2e\x19\x01\x01\x00", 7); // header?
write(fd, "T\x01\x2e\x19\x01\x01\x00", 7); // header (old piece format)
/* checksum */
hash = do_hash_file(file);
ptr[0]^=ptr[1]; ptr[1]=ptr[0]^ptr[1]; ptr[0]^=ptr[1];
write(fd, &hash, 2);
printf("hash: %04x\n", hash);
memset(bname, '\0', 13);
if (name == NULL)
name = fpid_file(file);
/* failback */
if (name == NULL)
name = file;
strncpy(bname, name, 12);
write(fd, bname, 12);
write(fd, &sz, 4);
if (version) {
/* append metadata */
write(fd, "\x00\x00\x00\x00\x31", 5);
len = strlen(version);
write(fd, &len, 1);
write(fd, version, len);
write(fd, "\x00\x9b", 2);
} else {
write(fd, "\x00\x00\x00\x00\x9b", 5);
}
// b4 00 00 00 00 36
if (read(fd, header, 5) != 5) {
printf("Error reading fiasco header\n");
goto __fiasco_read_image_end;
}
if (header[0] != 0xb4) {
printf("Invalid fiasco signature.\n");
goto __fiasco_read_image_end;
}
// skip 6 bytes
read(fd, version, 6);
// print version header
if (read(fd, version, 55) != 55) {
printf("Error reading fiasco version.\n");
goto __fiasco_read_image_end;
}
printf("# Fiasco header information:\n");
printf("# ==========================\n");
printf("# firmware type: %s\n", version);
version2 = version+strlen((char *)version)+3;
if (*version2=='.')
printf("firmware version: (null) (old firmware? no version string found?)\n");
else printf("firmware version: %s\n", version2);
// pieces:
// after the version2 string starts the header-body loop love
lseek(fd, 0xf + strlen(version2) + strlen(version), SEEK_SET);
do {
char piece_header[30];
char description[256];
unsigned char desc_len;
char *name;
off_t size;
off_t tmp = lseek(fd, 0, SEEK_CUR);
size = read(fd, piece_header, 30);
if (size != 30) {
fprintf(stderr, "Unexpected end of file\n");
while(1) {
ret = read(gd, buf, 4096);
if (ret<1)
break;
write(fd, buf, ret);
}
return 0;
}
int fiasco_pack(int optind, char *argv[])
{
const char *file = argv[optind];
char *type;
int fd, ret;
fd = fiasco_new(file, file); // TODO use a format here
if (fd == -1)
return 1;
printf("Package: %s\n", file);
while((file=argv[++optind])) {
type = (char *)fpid_file(file);
printf("Adding %s: %s..\n", type, file);
ret = fiasco_add(fd, type, file, NULL);
if (ret<0) {
printf("Error\n");
close(fd);
return 1;
}
dump_bytes(piece_header,30);
if (!piece_header_is_valid(piece_header)) {
fprintf(stderr, "Oops. Invalid piece header.\n");
break;
}
size = piece_header_to_size(piece_header);
name = piece_header_to_name(piece_header);
printf("# %s is %lld bytes\n", name, size);
read(fd, description, 255);
printf("# version: %s\n", description);
/* lseek foreach subimage */
lseek(fd, tmp, SEEK_SET);
lseek(fd, strlen(description) + 0x20, SEEK_CUR);
printf("rsc '%s' %lld '%s.bin' 0 %lld\n", file, lseek(fd,0,SEEK_CUR), name, size);
lseek(fd, size, SEEK_CUR);
} while(1);
//printf("Image '%s', size %d bytes.\n", image, size);
__fiasco_read_image_end:
}
fiasco_add_eof(fd);
printf("Done!\n");
close(fd);
return 0;
}
/* local code */
#if 0
void my_callback(int fd, struct header_t *header)
{
fiasco_data_read(header);
//read(fd, buf, header->size);
printf("Dumping %s\n", header->name);
printf("DATA: %02x\n", header->data[0]);
fiasco_data_free(header);
}
int main(int argc, char **argv)
{
if (argc!=2) {
printf("Usage: unfiasco [file]\n");
return 1;
}
/*
fd = fiasco_new("myfiasco", "pancake-edition");
fiasco_add(fd, "kernel", "zImage", "2.6.22");
close(fd);
*/
// fiasco_callback = &my_callback;
return openfiasco(argv[1]);
}
#endif
+45 -15
View File
@@ -1,25 +1,24 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include "hash.h"
#include "hexdump.h"
#include <usb.h>
#include <stdio.h>
#include <string.h>
@@ -32,6 +31,26 @@ void check_nolo_order_failed()
exit(1);
}
void query_error_message()
{
/* query error message */
int len = 0;
char nolomsg[2048];
memset(nolomsg, '\0', 2048);
usb_control_msg(dev, 192, 5, 0, 0, nolomsg, 2048, 2000);
nolomsg[2047] = '\0';
printf("\nNOLO says:\n");
if (nolomsg[0] == '\0') {
printf(" (.. silence ..)\n");
} else {
dump_bytes((unsigned char *)nolomsg, 128);
do {
printf(" - %s\n", nolomsg+len);
len+=strlen(nolomsg+len)+1;
} while(nolomsg[len]!='\0');
}
}
void check_nolo_order()
{
int i, xlo = 0;
@@ -100,6 +119,7 @@ void flash_image(char *filename, char *piece, char *version)
//dump_bytes(fquery, 27+vlen);
if (usb_control_msg(dev, CMD_WRITE, request, 0, 0, (char *)fquery, 27+vlen, 2000) <0) {
query_error_message();
perror("flash_image.header");
exit(1);
}
@@ -123,8 +143,18 @@ void flash_image(char *filename, char *piece, char *version)
if (bread != 1)
printf("WARNING: Oops wrong read %d vs %d \n", bread, bsize);
bread = usb_bulk_write(dev, 2, buf, bsize, 5000);
if (bread == 64) {
query_error_message();
fclose(fd);
return;
}
progressbar(off, size);
if (bread<0) perror(" -ee- ");
if (bread<0) {
printf("\n");
perror(" -ee- ");
fclose(fd);
return;
}
fflush(stdout);
}
fclose(fd);
+16 -19
View File
@@ -1,28 +1,26 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
char *fpid_file(char *filename)
const char *fpid_file(const char *filename)
{
FILE *fd;
char buf[512];
@@ -47,11 +45,9 @@ char *fpid_file(char *filename)
size = ftell(fd);
fclose(fd);
#if 0
if (!memcmp(b+0x34, "2NDAPE", 6))
return PIECE_2ND;
return pieces[PIECE_2ND];
else
#endif
if (!memcmp(b+0x04, "NOLOScnd", 8))
return pieces[PIECE_SECONDARY];
else
@@ -64,7 +60,8 @@ char *fpid_file(char *filename)
if (!memcmp(b+0x00, "\x00\x00\xa0\xe1\x00\x00\xa0\xe1", 8))
return pieces[PIECE_KERNEL];
else
if (!memcmp(b+0x00, "\x85\x19\x01\xe0", 4)) {
// JFFS2 MAGIC
if (!memcmp(b+0x00, "\x85\x19", 2)) { //\x01\xe0", 4)) {
/*/ is jffs2 */
if (size < 0x300000)
return pieces[PIECE_INITFS];
+12 -14
View File
@@ -1,21 +1,19 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
+12 -14
View File
@@ -1,21 +1,19 @@
/*
* Copyright (C) 2006-2007
* pancake <pancake@youterm.com>
* radare - advanced commandline hexadecimal editor
* Copyright (C) 2006,2007 pancake <pancake@youterm.com>
*
* radare is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* radare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with radare; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
+203 -179
View File
@@ -1,25 +1,23 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <usb.h>
#include "query.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -28,20 +26,23 @@
/* global pr0n */
struct usb_device *device = NULL;
struct usb_dev_handle *dev = NULL;
char *fiasco_image = NULL;
char *boot_cmdline = NULL;
char *reverseto = NULL;
int rdflags = -1;
int usb_mode = -1;
int verbose = 0;
int identify = 0;
int reboot = 0;
int unpack = 0;
int info = 0;
char *fiasco_image = NULL;
char *boot_cmdline = NULL;
char *reverseto = NULL;
int rd_mode = -1;
int rd_flags = -1;
int usb_mode = -1;
int root_device = -1;
int verbose = 0;
int identify = 0;
int reboot = 0;
int unpack = 0;
int info = 0;
/* global structs */
char *pieces[] = {
"xloader", // xloader.bin
"2nd", // 2nd
"secondary", // secondary.bin
"kernel", // zImage
"initfs", // jffs'd initfs
@@ -63,103 +64,39 @@ char *root_devices[] = {
NULL
};
struct devices {
char *name;
unsigned short vendor_id;
unsigned short product_id;
unsigned short flags;
};
#define SUPPORTED_DEVICES 5
struct devices supported_devices[SUPPORTED_DEVICES] = {
{ "unkn", 0x421, 0x3f00, 0x0000 }, // probably a development board
{ "n770", 0x421, 0x0105, 0x0001 }, // my n770
{ "n800", 0x421, 0x04c3, 0x0001 }, // a n800
{ 0 },
{ 0 }
};
int is_valid_device(struct usb_device_descriptor *udd)
{
int i;
struct devices ptr = supported_devices[0];
for(i=0 ; ptr.vendor_id; ptr = supported_devices[++i])
if ((udd->idVendor == ptr.vendor_id)
&& (udd->idProduct == ptr.product_id)) {
printf("found %s (%04x:%04x)\n",
ptr.name, ptr.vendor_id, ptr.product_id);
return 1;
}
return 0;
}
void list_valid_devices()
{
int i;
struct devices ptr = supported_devices[0];
for(i=0; ptr.vendor_id; ptr = supported_devices[++i])
printf("%04x:%04x %s\n", ptr.vendor_id, ptr.product_id, ptr.name);
}
int usb_device_found(struct usb_device_descriptor *udd)
{
if (usb_find_busses() < 0) {
fprintf(stderr, "error: no usb busses found.\n");
exit(1);
} else {
if (usb_find_devices() < 0) {
fprintf(stderr, "error: no devices found.\n");
exit(1);
} else {
struct usb_bus *bus;
for (bus = usb_busses; bus; bus = bus->next) {
struct usb_device *dev = bus->devices;
D printf("bus: \n");
for (; dev; dev = dev->next) {
*udd = dev->descriptor;
D printf(" dev (%s) - ", dev->filename);
D printf("vendor: %04x product: %04x\n", udd->idVendor, udd->idProduct);
if (is_valid_device(udd)) {
device = dev;
return 1;
}
}
}
}
}
return 0;
}
/*------------- devices -----------------------*/
void show_title()
{
printf("0xFFFF v%s - The Free Fiasco Firmware Flasher\n", VERSION);
printf("0xFFFF v%s // The Free Fiasco Firmware Flasher\n", VERSION);
}
void show_usage()
{
int i;
show_title();
printf(" -b [arg] boots the kernel with arguments\n");
printf(" -e [path] dump and extract pieces to path\n");
printf(" -p [[p%%]file] piece-of-firmware %% file-where-this-piece-is\n");
printf(" -r [0|1] disable/enable R&D mode\n");
printf(" -u [fiasco] unpack target fiasco image\n");
printf(" -U [0|1] disable/enable the usb host mode\n");
printf(" -h show this help message\n");
printf(" -i show device information (let standby mode)\n");
printf(" -I [piece] identify a firmware piece\n");
printf(" -l list supported usb device ids\n");
printf(" -d [vid:pid] injects a usb device into the supported list\n");
printf(" -R reboot the omap board\n");
printf(" -v be verbose and noisy\n");
printf(" -V show 0xFFFF version information\n");
printf(" -b [arg] boots the kernel with arguments\n");
printf(" -c console prompt mode\n");
printf(" -C [/dev/mtd] check bad blocks on mtd\n");
printf(" -d [vid:pid] injects a usb device into the supported list\n");
printf(" -D [0|1|2] sets the root device to flash (0), mmc (1) or usb (2)\n");
printf(" -e [path] dump and extract pieces to path\n");
printf(" -f <flags> set the given RD flags (see '-f help')\n");
printf(" -F [fiasco] flash a fiasco firmware image\n");
printf(" -h show this help message\n");
printf(" -H [file] calculate hash for file\n");
printf(" -i show device information (let standby mode)\n");
printf(" -I [piece] identify a firmware piece\n");
printf(" -l, -L list supported usb device ids\n");
printf(" -p [[p%%]file] piece-of-firmware %% file-where-this-piece-is\n");
printf(" -P [new-fiasco] creates a new fiasco package, pieces as arguments\n");
printf(" -r [0|1] disable/enable R&D mode\n");
printf(" -R reboot the omap board\n");
printf(" -s [serial] serial port console (minicom like terminal)\n");
printf(" -u [fiasco] unpack target fiasco image\n");
printf(" -U [0|1] disable/enable the usb host mode\n");
printf(" -v be verbose and noisy\n");
printf(" -V show 0xFFFF version information\n");
printf(" -x extract configuration entries from /dev/mtd1\n");
printf("Pieces are: ");
for(i=0;pieces[i];i++) printf("%s ", pieces[i]); printf("\n");
// serial port support is not yet done (cold flash is for flashing the 8kB nand)
@@ -168,53 +105,153 @@ void show_usage()
exit(0);
}
void unpack_fiasco_image(char *file)
void unpack_callback(struct header_t *header)
{
fiasco_read_image(file);
// TODO
FILE *fd = fopen(header->name, "wb");
if (fd == NULL) {
printf("Cannot open file.\n");
return;
}
fiasco_data_read(header);
fwrite(header->data, header->size, 1, fd);
fclose(fd);
}
int query_sw_version()
void unpack_fiasco_image(char *file)
{
int ret;
char bytes[1024];
printf("Dumping firmware pieces to disk.\n");
fiasco_callback = &unpack_callback;
openfiasco( file );
}
strcpy(bytes, "version:sw-release");
ret = usb_control_msg(dev, CMD_WRITE, 18, 0, 0, (char *)&bytes, 18, 2000);
if (ret<0) {
fprintf(stderr, "error: cannot write query 18\n");
return 0;
}
ret = usb_control_msg(dev, CMD_QUERY, 20, 0, 0, (char *)&bytes, 512, 2000);
if (ret<0) {
fprintf(stderr, "error: b0rken swversion read!\n");
return 0;
}
printf("SWVERSION GOT: %s\n", bytes); //???+strlen(bytes)+1));
return 1;
int fiasco_flash(char *file)
{
/* TODO */
fiasco_callback = NULL;
openfiasco( file );
printf("\nTODO: Implement the fiasco flashing here.\n");
}
int connect_via_usb()
{
struct usb_device_descriptor udd;
struct devices it_device;
int c = 0;
static char pbc[]={'/','-','\\', '|'};
// usb_set_debug(5);
usb_init();
/* Tries to get access to the Internet Tablet and retries
* if any of the neccessary steps fail.
*
* Note: While a proper device may be found on the bus it may
* not be in the right state to be accessed (e.g. the Nokia is
* not in the boot stage any more).
*/
while(!dev) {
usleep(0xc350); // 0.5s
if(!usb_device_found(&udd, &it_device)) {
printf("\rWaiting for device... %c", pbc[++c%4]);
fflush(stdout);
continue;
}
/* open device */
if(!(dev = usb_open(device))) {
perror("usb_open");
return 1;
}
if ( usb_claim_interface(dev, 2) < 0) { // 2 or 0
D perror("usb_claim_interface");
// Something is broken if closing fails.
if(usb_close(dev)) {
perror("usb_close");
return 1;
}
dev = NULL;
// Try again later.
continue;
}
if (usb_set_altinterface(dev, 1) < 0) {
D perror("usb_set_altinterface");
// Something is broken if closing fails.
if(usb_close(dev)) {
perror("usb_close");
return 1;
}
dev = NULL;
// Try again later.
continue;
}
}
printf("found %s (%04x:%04x)\n", it_device.name,
it_device.vendor_id, it_device.product_id);
/* go go go! */
while(get_status());
sleep(1); // take breath
return 0;
}
int main(int argc, char **argv)
{
struct usb_device_descriptor udd;
int c;
while((c = getopt(argc, argv, "p:vVhRu:ib:U:r:e:ld:I:")) != -1) {
while((c = getopt(argc, argv, "C:cp:PvVhRu:ib:U:r:e:Lld:I:D:f:F:s:xH:")) != -1) {
switch(c) {
case 'H':
printf("xorpair: %04x\n", do_hash_file(optarg));
return 0;
case 'x':
return dump_config();
case 'c':
return console_prompt();
case 'F':
return fiasco_flash(optarg);
case 'd':
sscanf(optarg, "%04hx:%04hx",
&supported_devices[SUPPORTED_DEVICES-2].vendor_id,
&supported_devices[SUPPORTED_DEVICES-2].product_id);
supported_devices[SUPPORTED_DEVICES-2].name = strdup("user");
break;
case 'D':
root_device = atoi(optarg);
break;
case 'e':
reverseto = optarg;
break;
case 's':
return console(optarg);
case 'f':
if (!strcmp(optarg,"help")) {
printf("* Flags are composed of:\n");
printf(" 0x02 - disable OMAP watchdog (possibly)\n");
printf(" 0x04 - disable RETU watchdog (possibly)\n");
printf(" 0x08 - disable lifeguard reset\n");
printf(" 0x10 - enable serial console\n");
printf(" 0x20 - disable USB timeout\n");
exit(1);
}
rd_flags = (unsigned short) strtoul(optarg, NULL, 16);
case 'U':
usb_mode = atoi(optarg);
break;
case 'r':
rdflags = atoi(optarg);
rd_mode = atoi(optarg);
break;
case 'b':
boot_cmdline = optarg;
@@ -226,6 +263,9 @@ int main(int argc, char **argv)
case 'p':
add_piece(optarg);
break;
case 'P':
return fiasco_pack(optind, argv);
case 'L':
case 'l':
list_valid_devices();
return 0;
@@ -233,6 +273,8 @@ int main(int argc, char **argv)
printf("%s: %s\n", fpid_file(optarg), optarg);
identify = 1;
break;
case 'C':
return check_badblocks(optarg);
case 'i':
info = 1;
break;
@@ -259,13 +301,16 @@ int main(int argc, char **argv)
&& (boot_cmdline == NULL)
&& (reverseto == NULL)
&& (pcs_n == 0)
&& (rdflags == -1)
&& (rd_flags == -1)
&& (rd_mode == -1)
&& (info == 0)
&& (reboot == 0)
&& (usb_mode == -1))
&& (usb_mode == -1)
&& (root_device == -1))
{
printf("Usage: 0xFFFF [-hvVRi] [-e path] [-U 0|1] [-p [piece%]file [-p ...]]\n");
printf(" [-b boot-args] [-I piece [-I ...]] [-u fiasco-image]\n");
printf("0xFFFF [-chiLRvVx] [-C mtd-dev] [-d vid:pid] [-D 0|1|2] [-e path] [-f flags]\n");
printf(" [-F fiasco] [-H hash-file] [-I piece] [-p [piece%%]file]] [-r 0|1]\n");
printf(" [-s serial-dev] [-u fiasco-image] [-U 0|1] | [-P new-fiasco] [piece1] [2] ..\n");
return 1;
}
@@ -279,50 +324,20 @@ int main(int argc, char **argv)
return 0;
}
// usb_set_debug(5);
usb_init();
while(!usb_device_found(&udd)) {
char pbc[]={'/','-','\\', '|'};
usleep(0xc350); // 0.5s
printf("\rWaiting for device... %c", pbc[++c%4]);
fflush(stdout);
}
/*/ open device */
dev = usb_open(device);
if (dev == NULL) {
perror("usb_open");
return 1;
}
// TODO
if ( usb_claim_interface(dev, 2) < 0) { // 2 or 0
perror("usb_claim_interface");
return 1;
}
if (usb_set_altinterface(dev, 1) < 0) {
perror("usb_set_altinterface");
return 1;
}
set_rd_mode(rdflags);
/* go go go! */
while(get_status());
if (connect_via_usb()) {
fprintf(stderr, "Cannot connect to device. It is possibly not in boot stage.\n");
return 0;
}
// if (info)
sleep(1); // take breath
query_root_device(); // only for flashing
query_rdmode_device();
query_hw_revision(); // get hardware revision:
cmd_info("");
if (pcs_n) {
int c;
check_nolo_order();
query_sw_version();
query_nolo_version();
get_sw_version();
get_nolo_version();
for(c=0;c<pcs_n;c++) {
printf("Flashing %s (%s)\n", pcs[c].type, pcs[c].name);
@@ -330,8 +345,17 @@ int main(int argc, char **argv)
}
}
if (usb_mode!=-1)
set_usb_host_mode(usb_mode);
if (rd_mode != -1)
set_rd_mode(rd_mode);
if (rd_flags != -1)
set_rd_flags(rd_flags);
if (root_device != -1)
set_root_device(root_device);
if (usb_mode != -1)
set_usb_mode(usb_mode);
if (boot_cmdline)
boot_board(boot_cmdline);
+52 -12
View File
@@ -1,9 +1,13 @@
#ifndef _INCLUDE_MAIN_H_
#define _INCLUDE_MAIN_H_
#define _FILE_OFFSET_BITS 64
#define _GNU_SOURCE
// Forward declaration for use in function arguments.
struct devices;
int reverse_extract_pieces(char *dir);
void flash_image(char *filename, char *piece, char *version);
int fiasco_read_image(char *file);
@@ -11,20 +15,26 @@ void check_nolo_order();
extern struct usb_dev_handle *dev;
unsigned long get_file_size(char *file);
void progressbar(unsigned long long part, unsigned long long total);
int get_status();
int get_peripheral_host_mode(int foo);
int boot_board(char *cmdline);
int boot_board(char *cmdline);
int reboot_board();
char *fpid_file(char *filename);
int set_rd_mode(unsigned short mode);
int set_usb_host_mode(unsigned short mode);
int query_hw_revision();
int query_rdmode_device();
int query_root_device();
int query_nolo_version();
const char *fpid_file(const char *filename);
int add_piece(char *piece);
#include <usb.h>
extern struct usb_device *device;
extern struct usb_dev_handle *dev;
int is_valid_device(struct usb_device_descriptor *udd);
void list_valid_devices();
int usb_device_found(struct usb_device_descriptor *udd, struct devices *it_device);
int console(const char *device);
int connect_via_usb();
int console_prompt();
//
void cmd_info(char *line);
int check_badblocks(char *mtddev);
int dump_config();
extern int verbose;
#define D if (verbose)
#define CMD_WRITE 64
@@ -40,11 +50,22 @@ struct piece_t {
char *vers;
};
struct devices {
char *name;
unsigned short vendor_id;
unsigned short product_id;
unsigned short flags;
};
#define SUPPORTED_DEVICES 6
extern struct devices supported_devices[SUPPORTED_DEVICES];
extern int pcs_n;
extern struct piece_t pcs[10];
enum {
PIECE_XLOADER = 0,
PIECE_2ND,
PIECE_SECONDARY,
PIECE_KERNEL,
PIECE_INITFS,
@@ -57,4 +78,23 @@ extern char *pieces[];
extern char *modes[];
extern char *root_devices[];
// fiasco
int openfiasco(char *name);
int fiasco_new(const char *filename, const char *name);
void fiasco_data_read(struct header_t *header);
int fiasco_add_eof(int fd);
extern void (*fiasco_callback)(struct header_t *header);
int fiasco_add(int fd, const char *name, const char *file, const char *version);
int fiasco_pack(int optind, char *argv[]);
struct header_t {
int fd;
char fwname[128];
char name[128];
char version[128];
unsigned short hash;
unsigned int size;
unsigned char *data;
};
#endif
+76
View File
@@ -0,0 +1,76 @@
/*
* $Id: ftl.h,v 1.7 2005/11/07 11:14:54 gleixner Exp $
*
* Derived from (and probably identical to):
* ftl.h 1.7 1999/10/25 20:23:17
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef __MTD_FTL_USER_H__
#define __MTD_FTL_USER_H__
typedef struct erase_unit_header_t {
u_int8_t LinkTargetTuple[5];
u_int8_t DataOrgTuple[10];
u_int8_t NumTransferUnits;
u_int32_t EraseCount;
u_int16_t LogicalEUN;
u_int8_t BlockSize;
u_int8_t EraseUnitSize;
u_int16_t FirstPhysicalEUN;
u_int16_t NumEraseUnits;
u_int32_t FormattedSize;
u_int32_t FirstVMAddress;
u_int16_t NumVMPages;
u_int8_t Flags;
u_int8_t Code;
u_int32_t SerialNumber;
u_int32_t AltEUHOffset;
u_int32_t BAMOffset;
u_int8_t Reserved[12];
u_int8_t EndTuple[2];
} erase_unit_header_t;
/* Flags in erase_unit_header_t */
#define HIDDEN_AREA 0x01
#define REVERSE_POLARITY 0x02
#define DOUBLE_BAI 0x04
/* Definitions for block allocation information */
#define BLOCK_FREE(b) ((b) == 0xffffffff)
#define BLOCK_DELETED(b) (((b) == 0) || ((b) == 0xfffffffe))
#define BLOCK_TYPE(b) ((b) & 0x7f)
#define BLOCK_ADDRESS(b) ((b) & ~0x7f)
#define BLOCK_NUMBER(b) ((b) >> 9)
#define BLOCK_CONTROL 0x30
#define BLOCK_DATA 0x40
#define BLOCK_REPLACEMENT 0x60
#define BLOCK_BAD 0x70
#endif /* __MTD_FTL_USER_H__ */
+91
View File
@@ -0,0 +1,91 @@
/*
* $Id: inftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
*
* Parts of INFTL headers shared with userspace
*
*/
#ifndef __MTD_INFTL_USER_H__
#define __MTD_INFTL_USER_H__
#define OSAK_VERSION 0x5120
#define PERCENTUSED 98
#define SECTORSIZE 512
/* Block Control Information */
struct inftl_bci {
uint8_t ECCsig[6];
uint8_t Status;
uint8_t Status1;
} __attribute__((packed));
struct inftl_unithead1 {
uint16_t virtualUnitNo;
uint16_t prevUnitNo;
uint8_t ANAC;
uint8_t NACs;
uint8_t parityPerField;
uint8_t discarded;
} __attribute__((packed));
struct inftl_unithead2 {
uint8_t parityPerField;
uint8_t ANAC;
uint16_t prevUnitNo;
uint16_t virtualUnitNo;
uint8_t NACs;
uint8_t discarded;
} __attribute__((packed));
struct inftl_unittail {
uint8_t Reserved[4];
uint16_t EraseMark;
uint16_t EraseMark1;
} __attribute__((packed));
union inftl_uci {
struct inftl_unithead1 a;
struct inftl_unithead2 b;
struct inftl_unittail c;
};
struct inftl_oob {
struct inftl_bci b;
union inftl_uci u;
};
/* INFTL Media Header */
struct INFTLPartition {
__u32 virtualUnits;
__u32 firstUnit;
__u32 lastUnit;
__u32 flags;
__u32 spareUnits;
__u32 Reserved0;
__u32 Reserved1;
} __attribute__((packed));
struct INFTLMediaHeader {
char bootRecordID[8];
__u32 NoOfBootImageBlocks;
__u32 NoOfBinaryPartitions;
__u32 NoOfBDTLPartitions;
__u32 BlockMultiplierBits;
__u32 FormatFlags;
__u32 OsakVersion;
__u32 PercentUsed;
struct INFTLPartition Partitions[4];
} __attribute__((packed));
/* Partition flag types */
#define INFTL_BINARY 0x20000000
#define INFTL_BDTL 0x40000000
#define INFTL_LAST 0x80000000
#endif /* __MTD_INFTL_USER_H__ */
+82
View File
@@ -0,0 +1,82 @@
/*
* $Id: jffs2-user.h,v 1.1 2004/05/05 11:57:54 dwmw2 Exp $
*
* JFFS2 definitions for use in user space only
*/
#ifndef __JFFS2_USER_H__
#define __JFFS2_USER_H__
/* This file is blessed for inclusion by userspace */
#include <linux/jffs2.h>
#include <endian.h>
#include <byteswap.h>
#undef cpu_to_je16
#undef cpu_to_je32
#undef cpu_to_jemode
#undef je16_to_cpu
#undef je32_to_cpu
#undef jemode_to_cpu
extern int target_endian;
#define t16(x) ({ uint16_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); })
#define t32(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); })
#define cpu_to_je16(x) ((jint16_t){t16(x)})
#define cpu_to_je32(x) ((jint32_t){t32(x)})
#define cpu_to_jemode(x) ((jmode_t){t32(x)})
#define je16_to_cpu(x) (t16((x).v16))
#define je32_to_cpu(x) (t32((x).v32))
#define jemode_to_cpu(x) (t32((x).m))
#define le16_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x))
#define le32_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x))
#define cpu_to_le16(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x))
#define cpu_to_le32(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x))
/* XATTR/POSIX-ACL related definition */
/* Namespaces copied from xattr.h and posix_acl_xattr.h */
#define XATTR_USER_PREFIX "user."
#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
#define XATTR_SECURITY_PREFIX "security."
#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
#define POSIX_ACL_XATTR_ACCESS "system.posix_acl_access"
#define POSIX_ACL_XATTR_ACCESS_LEN (sizeof (POSIX_ACL_XATTR_ACCESS) - 1)
#define POSIX_ACL_XATTR_DEFAULT "system.posix_acl_default"
#define POSIX_ACL_XATTR_DEFAULT_LEN (sizeof (POSIX_ACL_XATTR_DEFAULT) - 1)
#define XATTR_TRUSTED_PREFIX "trusted."
#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
struct jffs2_acl_entry {
jint16_t e_tag;
jint16_t e_perm;
jint32_t e_id;
};
struct jffs2_acl_entry_short {
jint16_t e_tag;
jint16_t e_perm;
};
struct jffs2_acl_header {
jint32_t a_version;
};
/* copied from include/linux/posix_acl_xattr.h */
#define POSIX_ACL_XATTR_VERSION 0x0002
struct posix_acl_xattr_entry {
uint16_t e_tag;
uint16_t e_perm;
uint32_t e_id;
};
struct posix_acl_xattr_header {
uint32_t a_version;
struct posix_acl_xattr_entry a_entries[0];
};
#endif /* __JFFS2_USER_H__ */
+158
View File
@@ -0,0 +1,158 @@
/*
* $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
*
* Portions of MTD ABI definition which are shared by kernel and user space
*/
#ifndef __MTD_ABI_H__
#define __MTD_ABI_H__
#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into
separate files was to avoid #ifdef __KERNEL__ */
#define __user
#endif
struct erase_info_user {
uint32_t start;
uint32_t length;
};
struct mtd_oob_buf {
uint32_t start;
uint32_t length;
unsigned char __user *ptr;
};
#define MTD_ABSENT 0
#define MTD_NORFLASH 3
#define MTD_NANDFLASH 4
#define MTD_DATAFLASH 6
#define MTD_GENERIC_TYPE 7
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
#define MTD_NO_ERASE 0x1000 /* No erase necessary */
// Some common devices / combinations of capabilities
#define MTD_CAP_ROM 0
#define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
#define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE)
#define MTD_CAP_NANDFLASH (MTD_WRITEABLE)
// Types of automatic ECC/Checksum available
#define MTD_ECC_NONE 0 // No automatic ECC available
#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip
#define MTD_ECC_SW 2 // SW ECC for Toshiba & Samsung devices
/* ECC byte placement */
#define MTD_NANDECC_OFF 0 // Switch off ECC (Not recommended)
#define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode)
#define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme
#define MTD_NANDECC_PLACEONLY 3 // Use the given placement in the structure (Do not store ecc result on read)
#define MTD_NANDECC_AUTOPL_USR 4 // Use the given autoplacement scheme rather than using the default
/* OTP mode selection */
#define MTD_OTP_OFF 0
#define MTD_OTP_FACTORY 1
#define MTD_OTP_USER 2
struct mtd_info_user {
uint8_t type;
uint32_t flags;
uint32_t size; // Total size of the MTD
uint32_t erasesize;
uint32_t writesize;
uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
uint32_t ecctype;
uint32_t eccsize;
};
struct region_info_user {
uint32_t offset; /* At which this region starts,
* from the beginning of the MTD */
uint32_t erasesize; /* For this region */
uint32_t numblocks; /* Number of blocks in this region */
uint32_t regionindex;
};
struct otp_info {
uint32_t start;
uint32_t length;
uint32_t locked;
};
#define MEMGETINFO _IOR('M', 1, struct mtd_info_user)
#define MEMERASE _IOW('M', 2, struct erase_info_user)
#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf)
#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf)
#define MEMLOCK _IOW('M', 5, struct erase_info_user)
#define MEMUNLOCK _IOW('M', 6, struct erase_info_user)
#define MEMGETREGIONCOUNT _IOR('M', 7, int)
#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user)
#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo)
#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo)
#define MEMGETBADBLOCK _IOW('M', 11, loff_t)
#define MEMSETBADBLOCK _IOW('M', 12, loff_t)
#define OTPSELECT _IOR('M', 13, int)
#define OTPGETREGIONCOUNT _IOW('M', 14, int)
#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info)
#define OTPLOCK _IOR('M', 16, struct otp_info)
#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout)
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
#define MTDFILEMODE _IO('M', 19)
/*
* Obsolete legacy interface. Keep it in order not to break userspace
* interfaces
*/
struct nand_oobinfo {
uint32_t useecc;
uint32_t eccbytes;
uint32_t oobfree[8][2];
uint32_t eccpos[32];
};
struct nand_oobfree {
uint32_t offset;
uint32_t length;
};
#define MTD_MAX_OOBFREE_ENTRIES 8
/*
* ECC layout control structure. Exported to userspace for
* diagnosis and to allow creation of raw images
*/
struct nand_ecclayout {
uint32_t eccbytes;
uint32_t eccpos[64];
uint32_t oobavail;
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
};
/**
* struct mtd_ecc_stats - error correction status
*
* @corrected: number of corrected bits
* @failed: number of uncorrectable errors
* @badblocks: number of bad blocks in this partition
* @bbtblocks: number of blocks reserved for bad block tables
*/
struct mtd_ecc_stats {
uint32_t corrected;
uint32_t failed;
uint32_t badblocks;
uint32_t bbtblocks;
};
/*
* Read/write file modes for access to MTD
*/
enum mtd_file_modes {
MTD_MODE_NORMAL = MTD_OTP_OFF,
MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
MTD_MODE_OTP_USER = MTD_OTP_USER,
MTD_MODE_RAW,
};
#endif /* __MTD_ABI_H__ */
+21
View File
@@ -0,0 +1,21 @@
/*
* $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
*
* MTD ABI header for use by user space only.
*/
#ifndef __MTD_USER_H__
#define __MTD_USER_H__
#include <stdint.h>
/* This file is blessed for inclusion by userspace */
#include <mtd/mtd-abi.h>
typedef struct mtd_info_user mtd_info_t;
typedef struct erase_info_user erase_info_t;
typedef struct region_info_user region_info_t;
typedef struct nand_oobinfo nand_oobinfo_t;
typedef struct nand_ecclayout nand_ecclayout_t;
#endif /* __MTD_USER_H__ */
+76
View File
@@ -0,0 +1,76 @@
/*
* $Id: nftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $
*
* Parts of NFTL headers shared with userspace
*
*/
#ifndef __MTD_NFTL_USER_H__
#define __MTD_NFTL_USER_H__
/* Block Control Information */
struct nftl_bci {
unsigned char ECCSig[6];
uint8_t Status;
uint8_t Status1;
}__attribute__((packed));
/* Unit Control Information */
struct nftl_uci0 {
uint16_t VirtUnitNum;
uint16_t ReplUnitNum;
uint16_t SpareVirtUnitNum;
uint16_t SpareReplUnitNum;
} __attribute__((packed));
struct nftl_uci1 {
uint32_t WearInfo;
uint16_t EraseMark;
uint16_t EraseMark1;
} __attribute__((packed));
struct nftl_uci2 {
uint16_t FoldMark;
uint16_t FoldMark1;
uint32_t unused;
} __attribute__((packed));
union nftl_uci {
struct nftl_uci0 a;
struct nftl_uci1 b;
struct nftl_uci2 c;
};
struct nftl_oob {
struct nftl_bci b;
union nftl_uci u;
};
/* NFTL Media Header */
struct NFTLMediaHeader {
char DataOrgID[6];
uint16_t NumEraseUnits;
uint16_t FirstPhysicalEUN;
uint32_t FormattedSize;
unsigned char UnitSizeFactor;
} __attribute__((packed));
#define MAX_ERASE_ZONES (8192 - 512)
#define ERASE_MARK 0x3c69
#define SECTOR_FREE 0xff
#define SECTOR_USED 0x55
#define SECTOR_IGNORE 0x11
#define SECTOR_DELETED 0x00
#define FOLD_MARK_IN_PROGRESS 0x5555
#define ZONE_GOOD 0xff
#define ZONE_BAD_ORIGINAL 0
#define ZONE_BAD_MARKED 7
#endif /* __MTD_NFTL_USER_H__ */
+12 -14
View File
@@ -1,21 +1,19 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
+192 -46
View File
@@ -1,21 +1,19 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
@@ -28,7 +26,7 @@
int get_status()
{
int ret = 0;
if (usb_control_msg(dev, 192, 1, 0, 0, (char *)&ret, 4, 2000) == -1) {
if (usb_control_msg(dev, CMD_QUERY, 1, 0, 0, (char *)&ret, 4, 2000) == -1) {
fprintf(stderr, "Cannot get device status.\n");
exit(1);
}
@@ -36,26 +34,54 @@ int get_status()
return ret;
}
int get_peripheral_host_mode(int foo)
/**
* request type: CMD_WRITE
* request : 16
* value : 0|1 (=> client|host)
* index : 2
*/
int set_usb_mode(unsigned int mode)
{
//unsigned short mode = 0;
if (mode > 1)
{
printf("Invalid USB mode specified '%d'.\n", mode);
return -1;
}
if (usb_control_msg(dev, CMD_WRITE, 16, mode, 2, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set USB mode.\n");
return -1;
}
// XXX BROKEN
#if 0
if (usb_control_msg(dev, 64, 16, 2, 0, 2, 0, 0, 2000)) {
printf("Set USB mode to: '%s'.\n", (mode) ? "host" : "client");
return 0;
}
/**
* request type: CMD_QUERY
* request : 17
* index : 2
*
* return value: 0|1 (=> client|host)
*/
int get_usb_mode()
{
unsigned short mode = 0;
if (usb_control_msg(dev, CMD_QUERY, 17, 0, 2, (void *) &mode, sizeof(mode), 2000) == -1) {
fprintf(stderr, "Cannot query device.\n");
return -1;
}
printf("Device is in \"%s\" mode (%hd)\n", (mode)?"host":"peripheral", mode);
#endif
printf("Device's USB mode is '%s'\n", (mode) ? "host" : "client");
return 0;
}
/*
* boot the omap mobo
*/
/*
* Boots the Kernel with the given command-line.
*/
int boot_board(char *cmdline)
{
if (usb_control_msg(dev, CMD_WRITE, 130, 0, 0, cmdline, strlen(cmdline), 2000) == -1) {
@@ -70,7 +96,7 @@ int boot_board(char *cmdline)
}
/*
* reboot the omap mobo
* Reboots the omap mobo.
*/
int reboot_board()
{
@@ -100,23 +126,10 @@ int set_rd_mode(unsigned short mode)
return 0;
}
// mode = 1 || 0
int set_usb_host_mode(unsigned short mode)
{
if (usb_control_msg(dev, CMD_WRITE, 16, mode, 2, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot change the usb-host mode.\n");
return -1;
}
printf("USB host mode is %s.\n", mode?"enabled":"disabled");
return 0;
}
/*
* query root device
*/
int query_hw_revision()
int get_hw_revision()
{
unsigned char string[512];
int i = 0;
@@ -140,7 +153,7 @@ int query_hw_revision()
return 0;
}
int query_rdmode_device()
int get_rd_mode()
{
char isrd = 1;
@@ -153,11 +166,11 @@ int query_rdmode_device()
return isrd;
}
int query_root_device()
int get_root_device()
{
unsigned char opcode;
if (usb_control_msg(dev, 192, 17, 0, 1, (char *)&opcode, 1, 2000) < 0) {
if (usb_control_msg(dev, CMD_QUERY, 17, 0, 1, (char *)&opcode, 1, 2000) < 0) {
fprintf(stderr, "Cannot query root device\n");
return -1;
}
@@ -171,12 +184,124 @@ int query_root_device()
return 0;
}
int query_nolo_version()
/**
* request type: CMD_WRITE
* request : 16
* value : 0|1|2 (=> flash|mmc|usb)
* index : 1
*/
int set_root_device(unsigned short root_device)
{
if (root_device>2) {
printf("Invalid root device specified '%d'.\n", root_device);
return -1;
}
if (usb_control_msg(dev, CMD_WRITE, 16, root_device, 1, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set root device\n");
return -1;
}
printf("Root device set to: %s\n", root_devices[root_device]);
return 0;
}
/**
* Set flags:
* request type: CMD_WRITE
* request : 16
* value : flags to set, see below
* index : 3
*
* Clear flags:
* request type: CMD_WRITE
* request : 16
* value : flags to clear, see below
* index : 4
* Flags are composed of:
* 0x02 - disable OMAP watchdog (possibly)
* 0x04 - disable RETU watchdog (possibly)
* 0x08 - disable lifeguard reset
* 0x10 - enable serial console
* 0x20 - disable USB timeout
*
* The function encapsule the NOLO API in a way that it works like
* a chmod 707. The bits that are not set will be cleared after the
* call. This is done by issuing a 'clear flags' command with all the
* non set bits.
*
*/
int set_rd_flags(unsigned short flags)
{
unsigned short reverse_flags = 0;
if (flags & ~(0x02 | 0x04 | 0x08 | 0x10 | 0x20)) {
printf("Invalid rd flags specified '%x'.\n", flags);
return -1;
}
if (!(flags & 0x02))
reverse_flags |= 0x02;
if (!(flags & 0x04))
reverse_flags |= 0x04;
if (!(flags & 0x08))
reverse_flags |= 0x08;
if (!(flags & 0x10))
reverse_flags |= 0x10;
if (!(flags & 0x20))
reverse_flags |= 0x20;
if (usb_control_msg(dev, CMD_WRITE, 16, flags, 3, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set rd flags\n");
return -1;
}
if (usb_control_msg(dev, CMD_WRITE, 16, reverse_flags, 4, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set rd flags\n");
return -1;
}
printf("Set rd flags successfully!\n");
printf("disable OMAP watchdog : %s\n", (flags & 0x02) ? "set" : "not set");
printf("disable RETU watchdog : %s\n", (flags & 0x04) ? "set" : "not set");
printf("disable lifeguard reset: %s\n", (flags & 0x08) ? "set" : "not set");
printf("enable serial console : %s\n", (flags & 0x10) ? "set" : "not set");
printf("disable USB timeout : %s\n", (flags & 0x20) ? "set" : "not set");
return 0;
}
int get_rd_flags()
{
unsigned short flags = 0;
if (usb_control_msg(dev, CMD_QUERY, 17, 0, 3, (void *) &flags, sizeof(flags), 2000) == -1) {
fprintf(stderr, "Cannot get rd flags\n");
return -1;
}
printf("Current rd flag setting:\n");
printf("disable OMAP watchdog : %s\n", (flags & 0x02) ? "set" : "not set");
printf("disable RETU watchdog : %s\n", (flags & 0x04) ? "set" : "not set");
printf("disable lifeguard reset: %s\n", (flags & 0x08) ? "set" : "not set");
printf("enable serial console : %s\n", (flags & 0x10) ? "set" : "not set");
printf("disable USB timeout : %s\n", (flags & 0x20) ? "set" : "not set");
return 0;
}
int get_nolo_version()
{
unsigned int version; // ensure uint is at least 32 bits
//if (usb_control_msg(dev, 192, 3, 0, 1, (char *)&version, 4 , 2000) < 0) {
if (usb_control_msg(dev, 192, 3, 0, 0, (char *)&version, 4 , 2000) < 0) {
//if (usb_control_msg(dev, CMD_QUERY, 3, 0, 1, (char *)&version, 4 , 2000) < 0) {
if (usb_control_msg(dev, CMD_QUERY, 3, 0, 0, (char *)&version, 4 , 2000) < 0) {
fprintf(stderr, "Cannot query nolo version. Old bootloader version?\n");
exit(1);
}
@@ -191,3 +316,24 @@ int query_nolo_version()
return 0;
}
int get_sw_version()
{
int ret;
char bytes[1024];
strcpy(bytes, "version:sw-release");
ret = usb_control_msg(dev, CMD_WRITE, 18, 0, 0, (char *)&bytes, 18, 2000);
if (ret<0) {
fprintf(stderr, "error: cannot write query 18\n");
return 0;
}
ret = usb_control_msg(dev, CMD_QUERY, 20, 0, 0, (char *)&bytes, 512, 2000);
if (ret<0) {
fprintf(stderr, "error: b0rken swversion read!\n");
return 0;
}
printf("SWVERSION GOT: %s\n", bytes); //???+strlen(bytes)+1));
return 1;
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef QUERY_H_
#define QUERY_H_
int boot_board(char *cmdline);
int reboot_board();
int get_status();
int get_usb_mode();
int set_usb_mode(unsigned int);
int get_rd_mode();
int set_rd_mode(unsigned short mode);
int get_rd_flags();
int set_rd_flags(unsigned short flags);
int get_hw_revision();
int get_root_device();
int set_root_device(unsigned short);
int get_nolo_version();
int get_sw_version();
#endif /*QUERY_H_*/
+86
View File
@@ -0,0 +1,86 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <getopt.h>
int open_serial(const char *file)
{
struct termios tc;
int fd = open (file, O_RDWR | O_SYNC);
if (fd < 0) {
perror (file);
return -1;
}
// 115200 baud, 8n1, no flow control
tcgetattr(fd, &tc);
tc.c_iflag = IGNPAR;
tc.c_oflag = 0;
tc.c_cflag = CS8 | CREAD | CLOCAL;
tc.c_lflag = 0;
cfsetispeed(&tc, B115200);
cfsetospeed(&tc, B115200);
tcsetattr(fd, TCSANOW, &tc);
return fd;
}
int console(const char *device)
{
char str[513];
int fd = open_serial(device);
int pid;
if (fd == -1) {
fprintf(stderr, "Cannot open serial device %s\n", device);
return 1;
}
pid = fork();
if (pid) {
while(1) {
fgets(str, 512, stdin);
if (write(fd, str, strlen(str)-1) == -1) {
perror("write");
exit (1);
}
}
} else {
char buf;
while(1) {
if (read(fd, &buf,1) == -1) {
perror("read");
exit (1);
}
write(1, &buf, 1);
}
}
close(fd);
return 0;
}
+12 -14
View File
@@ -1,21 +1,19 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"