1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
|
Introduction to libnjb hacking
by Linus Walleij
------------------------------
This file contains some tips on how to get started if you want to
change stuff in libnjb, and some technical details we have found.
First, join the developer list at SourceForge, for details see
the project page at:
http://www.sourceforge.net/projects/libnjb/
Architecture and portability:
-----------------------------
Libnjb uses the libusb which in turn use the kernel of the host
operating system:
libnjb
|
libusb
|
kernel
When you're trying to fix a problem, first try to locate in which
layer of this sandwich the problem is located. This improves libnjb,
libusb and the kernel of your operating system at the same time,
and as other projects use libusb you help a *lot* of people when
you find bugs in libusb. See their homepage:
http://www.sourceforge.net/projects/libusb/
Libnjb+libusb+kernel has been verified to work with:
* Linux 2.4 and Linux 2.6 - issues remain with some USB 2.0
cards. (Kernel problems, not in our code.)
* FreeBSD
* MacOS X
It is maybe even possible to port libnjb to windows using
libusb-win32, which is still in the works. Noone has yet tried!
(http://libusb-win32.sourceforge.net/)
Suggested Projects:
-------------------
* Fully analyze and document the protocol.
* Implement a small HTTP server for our "samples" that can be used
for controlling the jukebox using only a web browser.
* Create a plugin for the GNOME Rhythmbox program in the same spirit
as the iPod plugin.
* Create a plugin for the MacOS X iTunes program.
USB Device ID:
--------------
Find the USB Device ID for a new device, in Linux by looking in
the file /proc/bus/usb/devices. Report this device ID to:
* The libnjb development team. (Through the mailing list
located at SourceForge.)
* The device database at http://www.linux-usb.org/usb.ids
(email at top of that file).
* The "usb.lst" device database used by Debian "discover-data" package
http://packages.debian.org/unstable/libs/discover-data.html
http://packages.qa.debian.org/d/discover-data.html
(More places?)
FireWire (IEEE 1394)
--------------------
Libnjb doesn't currently include support for FireWire. The reasons
are simple:
* None of the active developers have a FireWire device. Only the
Nomad Jukebox 3 and the first version of Nomad Jukebox Zen
have FireWire.
* We don't have any traces of how the FireWire traffic actually
look. It would be good for us to know, whether we start to
support it or not, so traces are welcomed.
As you see, this is a nice task for an eager developer to take on.
libraw1394 (http://sourceforge.net/projects/libraw1394) seem like
a good place to start for providing 1394 support to libnjb.
USB Traces:
-----------
When developing libnjb it may be necessary to compare the
functionality of libnjb with that of programs developed for
Microsoft Windows.
Most Linux developers that want to create a driver for something
running on Windows will try to intercept and decode USB traffic.
There exist several professional and expensive tools to do this,
both hardware and software. If you have such tools at your hands,
then it is good for you, and you'll probably be doing a very good
job at reverse-engineering the jukebox drivers.
Moste people do not have such delicate devices and will have to
resort to using software only. USB Snoopy is such a software tool
for Windows, that will try to intercept and log USB traffic to/from
any USB device:
http://www.wingmanteam.com/usbsnoopy/
Try to perform the parts of the behaviour that you want to capture
and make a log. If it is implemented in libnjb but fails, compare
the log to the result of running libnjb "sample" tools (found in
the "sample" directory of this library) with the debug flag -D7
(e.g ./handshake -D7) which will produce output similar to what
USB snoopy produces.
Device addition / adding new commands:
--------------------------------------
When you add a new device to libnjb (provided you know the
vendor and Device ID), you do this by:
* Adding the device in the "nomad.usermap" file
* Adding the appropriate definitons in "src/njbusb.h"
(don't forget the macros below the definitions)
* Adding detection code to "src/base.c"
* Adding any device-specific code in "src/base.c",
"src/procedure.c", "src/protocol3.h", "src/usb_io.c"
and the like.
Error codes:
------------
After almost every jukebox operation a 16-bit number is returned,
as a status code. Usually this code will be 0x0000 which means "OK".
The other possible values cannot be said to have been deeply
explored, and are simply just regarded as "errors" though some of
them may actually be informative. Normally libnjb will just write
out their occurance and leave it at that, doing nothing. If you
run into a certain new error code, try to figure out:
* The number (given)
* When it occurs, and thus what it means.
* How it is handled by the PlayCenter software, if it can be provoked
there.
* How we should implement code to handle the error.
Unimplemented commands:
-----------------------
The following commands are so far unimplemented in libnjb:
Nomad Jukebox 1 (src/protocol.c):
* Firmware upgrade - if you want to experiment with this you
are either insane or have a box of NJB:s to waste.
Nomad Jukebox 2, 3, Zen, Zen USB 2.0, NX, Xtra and the
Dell Digital Jukebox (src/protocol3.c):
* NJB_Get_EAX().
* NJB_Adjust_Sound() for anything else than the volume.
* Fast forward (skipping) in tracks.
* Things related to the njb3_get_keys() command
(see below).
* Firmware upgrade (see above).
Mysterious commands:
--------------------
At one time there was a discussion on the list about the
mysterious "AR00PL00SG00" command that has appeared on the newer
devices. We have no ideas as to what this actually is, we only
know that the command is related to a non-compulsory parameter
sent after each track- or file-transfer.
Newer devices, e.g. the Nomad Zen NX, has an "LG00" parameter
as well.
Such a parameter will typically look like this
0010 0001 Command
0000 0000 Zero?
000a Length of this command
0014 Metadata "0014"
0000 0000 Mysterious 32-bit number
0007 a3bd Mysterious 32-bit number
0000 Terminator
The "mysterious number" comes from the "AR00PL00SG00" "AR00"
record, where the metadata element named "0014" may be retrieved.
This record must first be retrieved by this command:
000c 0001 Command
0000 000a Command length
1400 Request a metadata record named "1400"
"get all ket-value pairs".
0006 Length of subrequest
000a Return metadata "000a"
0014 Return metadata "0014"
0015 Return metadata "0015" (Jukebox ID)
0000 Terminator
Metadata "000a" is the "AR00" "PL00" and "SG00" strings.
Metadata "0014" is that mysterious number
Metadata "0015" is the well-known jukebox ID.
Thus the "AR00", "PL00" and "SG00" are sort of key-value pairs.
The result of a 000c 0001-command may look like this:
0000: 0000 0006 000c 0000 0000 0006 000a 4152
0010: 3030 000a 0014 3e5f a8a7 0007 a3bd 0012
0020: 0015 0102 2502 3cff 09d9 4245 1311 3cff
0030: 09d9 0000 0006 000c 0000 0001 0006 000a
0040: 504c 3030 000a 0014 0000 0000 0000 0000
0050: 0012 0015 0102 2502 3cff 09d9 4245 1311
0060: 3cff 09d9 0000 0006 000c 0000 0002 0006
0070: 000a 5347 3030 000a 0014 0000 0000 0000
0080: 0000 0012 0015 0102 2502 3cff 09d9 4245
0090: 1311 3cff 09d9 0000 0000
Which has the following meaning/structure:
0000 status OK
0006 length of following field
000c PostID metadata tag
0000 0000 PostID for the AR00 thing
0006 length of following field
000a metadata "000a" = KEY
4152 3030 String "AR00"
000a Length of following field
0014 metadata "0014" = VALUE
3e5f a8a7 0007 a3bd "0014" value parameter to AR00
0012 Length of following field
0015 Device ID metadata tag
0102 2502 3cff 09d9 Device ID
4245 1311 3cff 09d9
0000 Zero terminator
0006 length of following field
000c PostID metadata tag
0000 0001 PostID for PL00, note +1 from AR00
0006 length of following field
000a metadata "000a" = KEY
504c 3030 String "PL00"
000a Length of following field
0014 metadata "0014" = VALUE
0000 0000 0000 0000 "0014" value parameter to PL00
0012 Length of following field
0015 Device ID metadata tag
0102 2502 3cff 09d9 Device ID
4245 1311 3cff 09d9
0000 Zero terminator
0006 length of following field
000c PostID metadata tag
0000 0002 PostID for the SG00 thing again +1
0006 length of following field
000a metadata "000a" = KEY
4152 3030 String "SG00"
000a length of following field
0014 metadata "0014" = VALUE
0000 0000 0000 0000 "0014" value parameter to SG00
0012 Length of following field
0015 Device ID metadata tag
0102 2502 3cff 09d9 Device ID
4245 1311 3cff 09d9
0000 Zero terminator
0000 Extra zero padding
So in this case the command returns the keys and values:
"AR00" = 3e5f a8a7, 0007 a3bd
"PL00" = 0000 0000, 0000 0000
"SG00" = 0000 0000, 0000 0000
A certain Nomad Zen NX produce the following dump:
0000: 00 00 00 06 00 0c 00 00 00 00 00 06 00 0a 41 52
0010: 30 30 00 0a 00 14 00 00 00 00 00 00 00 00 00 12
0020: 00 15 01 02 25 51 37 03 8b c7 e2 cf 10 27 37 03
0030: 8b c7 00 00 00 06 00 0c 00 00 00 02 00 06 00 0a
0040: 53 47 30 30 00 0a 00 14 00 00 00 00 00 00 00 00
0050: 00 12 00 15 01 02 25 51 37 03 8b c7 e2 cf 10 27
0060: 37 03 8b c7 00 00 00 06 00 0c 00 00 00 01 00 06
0070: 00 0a 50 4c 30 30 00 0a 00 14 00 00 00 00 00 00
0080: 00 00 00 12 00 15 01 02 25 51 37 03 8b c7 e2 cf
0090: 10 27 37 03 8b c7 00 00 00 06 00 0c 00 00 00 03
00a0: 00 06 00 0a 4c 47 30 30 00 0a 00 14 00 00 00 00
00b0: 00 00 00 00 00 12 00 15 01 02 25 51 37 03 8b c7
00c0: e2 cf 10 27 37 03 8b c7 00 00 00 00
"AR00" = 0000 0000, 0000 0000
"SG00" = 0000 0000, 0000 0000
"PL00" = 0000 0000, 0000 0000
"LG00" = 0000 0000, 0000 0000
The second part of the "AR00" key is then sent to the jukebox
alongside file- and track transfers. The first word will not
be sent, but is set to zero. God knows why. If you have a good
guess, then please tell us.
It is suspected that these keys may have something to do with
the Windows Media Audio (WMA) digital rights management (DRM)
system, which will most likely encrypt the files using the
Device ID and a previous seed from the jukebox. (So that the
keys seen contain the seed.)
This does not explain why the command 0010 0001 appear in
connection with MP3 files however. DRM:ed MP3:s?
The libnjb will currently read in and parse these keys, but
won't do anything with them.
SDMI compliant device ID:
-------------------------
The 16 byte (128 bit) long device ID of the Nomad Jukeboxes
were introduced to be SDMI compliant. The specification for
SDMI compliant portable devices says that a device ID shall be
atleast 32 bits if assigned by an authority, and atleast 128
bits if assigned randomly. I do not know if Creative actually
assign device ID:s at "random", but they behave as if they do.
Not that the Jukebox is SDMI compliant. It isn't. Nothing is,
really, because SDMI failed. Microsoft, however, use parts of
the ideas from SDMI in their DRM technology for WMA.
|