Package libprs500 :: Module prstypes
[hide private]
[frames] | no frames]

Source Code for Module libprs500.prstypes

  1  ##    Copyright (C) 2006 Kovid Goyal kovid@kovidgoyal.net 
  2  ##    This program is free software; you can redistribute it and/or modify 
  3  ##    it under the terms of the GNU General Public License as published by 
  4  ##    the Free Software Foundation; either version 2 of the License, or 
  5  ##    (at your option) any later version. 
  6  ## 
  7  ##    This program is distributed in the hope that it will be useful, 
  8  ##    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  9  ##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 10  ##    GNU General Public License for more details. 
 11  ## 
 12  ##    You should have received a copy of the GNU General Public License along 
 13  ##    with this program; if not, write to the Free Software Foundation, Inc., 
 14  ##    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 15   
 16  """ 
 17  Defines the structure of packets that are sent to/received from the device.  
 18   
 19  Packet structure is defined using classes and inheritance. Each class is a view that imposes 
 20  structure on the underlying data buffer. The data buffer is encoded in little-endian format, but you don't 
 21  have to worry about that if you are using the classes. The classes have instance variables with getter/setter functions defined 
 22  to take care of the encoding/decoding. The classes are intended to mimic C structs.  
 23   
 24  There are three kinds of packets. L{Commands<Command>}, L{Responses<Response>}, and L{Answers<Answer>}.  
 25  C{Commands} are sent to the device on the control bus, C{Responses} are received from the device,  
 26  also on the control bus. C{Answers} and their sub-classes represent data packets sent to/received from 
 27  the device via bulk transfers.  
 28   
 29  Commands are organized as follows: G{classtree Command} 
 30   
 31  You will typically only use sub-classes of Command.  
 32   
 33  Responses are organized as follows: G{classtree Response} 
 34   
 35  Responses inherit Command as they share header structure. 
 36   
 37  Answers are organized as follows: G{classtree Answer} 
 38  """ 
 39   
 40  import struct 
 41  from errors import PacketError 
 42   
 43  BYTE      = "<B"    #: Unsigned char little endian encoded in 1 byte 
 44  WORD      = "<H"    #: Unsigned short little endian encoded in 2 bytes 
 45  DWORD     = "<I"    #: Unsigned integer little endian encoded in 4 bytes 
 46  DDWORD    = "<Q"    #: Unsigned long long little endian encoded in 8 bytes 
 47   
 48   
49 -class TransferBuffer(list):
50 51 """ 52 Represents raw (unstructured) data packets sent over the usb bus. 53 54 C{TransferBuffer} is a wrapper around the tuples used by L{PyUSB<usb>} for communication. 55 It has convenience methods to read and write data from the underlying buffer. See 56 L{TransferBuffer.pack} and L{TransferBuffer.unpack}. 57 """ 58
59 - def __init__(self, packet):
60 """ 61 Create a L{TransferBuffer} from C{packet} or an empty buffer. 62 63 @type packet: integer or listable object 64 @param packet: If packet is a list, it is copied into the C{TransferBuffer} and then normalized (see L{TransferBuffer._normalize}). 65 If it is an integer, a zero buffer of that length is created. 66 """ 67 if "__len__" in dir(packet): 68 list.__init__(self, list(packet)) 69 self._normalize() 70 else: list.__init__(self, [0 for i in range(packet)])
71
72 - def __add__(self, tb):
73 """ Return a TransferBuffer rather than a list as the sum """ 74 return TransferBuffer(list.__add__(self, tb))
75
76 - def __getslice__(self, start, end):
77 """ Return a TransferBuffer rather than a list as the slice """ 78 return TransferBuffer(list.__getslice__(self, start, end))
79
80 - def __str__(self):
81 """ 82 Return a string representation of this buffer. 83 84 Packets are represented as hex strings, in 2-byte pairs, S{<=} 16 bytes to a line. An ASCII representation is included. For example:: 85 0700 0100 0000 0000 0000 0000 0c00 0000 ................ 86 0200 0000 0400 0000 4461 7461 ........Data 87 """ 88 ans, ascii = ": ".rjust(10,"0"), "" 89 for i in range(0, len(self), 2): 90 for b in range(2): 91 try: 92 ans += TransferBuffer.phex(self[i+b]) 93 ascii += chr(self[i+b]) if self[i+b] > 31 and self[i+b] < 127 else "." 94 except IndexError: break 95 ans = ans + " " 96 if (i+2)%16 == 0: 97 if i+2 < len(self): 98 ans += " " + ascii + "\n" + (TransferBuffer.phex(i+2)+": ").rjust(10, "0") 99 ascii = "" 100 last_line = ans[ans.rfind("\n")+1:] 101 padding = 50 - len(last_line) 102 ans += "".ljust(padding) + " " + ascii 103 return ans.strip()
104
105 - def unpack(self, fmt=DWORD, start=0):
106 """ 107 Return decoded data from buffer. 108 109 @param fmt: See U{struct<http://docs.python.org/lib/module-struct.html>} 110 @param start: Position in buffer from which to decode 111 """ 112 end = start + struct.calcsize(fmt) 113 return struct.unpack(fmt, "".join([ chr(i) for i in list.__getslice__(self, start, end) ]))
114
115 - def pack(self, val, fmt=DWORD, start=0):
116 """ 117 Encode C{val} and write it to buffer. 118 119 @param fmt: See U{struct<http://docs.python.org/lib/module-struct.html>} 120 @param start: Position in buffer at which to write encoded data 121 """ 122 self[start:start+struct.calcsize(fmt)] = [ ord(i) for i in struct.pack(fmt, val) ]
123
124 - def _normalize(self):
125 """ Replace negative bytes in C{self} by 256 + byte """ 126 for i in range(len(self)): 127 if self[i] < 0: 128 self[i] = 256 + self[i]
129 130 @classmethod
131 - def phex(cls, num):
132 """ 133 Return the hex representation of num without the 0x prefix. 134 135 If the hex representation is only 1 digit it is padded to the left with a zero. Used in L{TransferBuffer.__str__}. 136 """ 137 index, sign = 2, "" 138 if num < 0: 139 index, sign = 3, "-" 140 h=hex(num)[index:] 141 if len(h) < 2: 142 h = "0"+h 143 return sign + h
144 145 146
147 -class Command(TransferBuffer):
148 149 """ Defines the structure of command packets sent to the device. """ 150
151 - def __init__(self, packet):
152 """ 153 @param packet: len(packet) > 15 or packet > 15 154 """ 155 if ("__len__" in dir(packet) and len(packet) < 16) or ("__len__" not in dir(packet) and packet < 16): 156 raise PacketError(str(self.__class__)[7:-2] + " packets must have length atleast 16") 157 TransferBuffer.__init__(self, packet)
158 159 @apply
160 - def number():
161 doc =\ 162 """ 163 Command number. C{unsigned int} stored in 4 bytes at byte 0. 164 165 Observed command numbers are: 166 1. 0x00 167 Test bulk read 168 2. 0x01 169 End session 170 3. 0x0101 171 Ask for device information 172 4. 0x1000 173 Acknowledge 174 5. 0x107 175 Purpose unknown, occurs in the beginning of sessions duing command testing. Best guess is some sort of OK packet 176 6. 0x106 177 Purpose unknown, occurs in the beginning of sessions duing command testing. Best guess is some sort of OK packet 178 7. 0x18 179 Ask for information about a file 180 8. 0x33 181 Open directory for reading 182 9. 0x34 183 Close directory 184 10. 0x35 185 Ask for next item in the directory 186 11. 0x10 187 File open command 188 12. 0x11 189 File close command 190 13. 0x16 191 File read command 192 """ 193 def fget(self): 194 return self.unpack(start=0, fmt=DWORD)[0]
195 196 def fset(self, val): 197 self.pack(val, start=0, fmt=DWORD)
198 199 return property(**locals()) 200 201 @apply
202 - def type():
203 doc =\ 204 """ Command type. C{unsigned long long} stored in 8 bytes at byte 4. Known types 0x00, 0x01. Not sure what the type means. """ 205 def fget(self): 206 return self.unpack(start=4, fmt=DDWORD)[0]
207 208 def fset(self, val): 209 self.pack(val, start=4, fmt=DDWORD) 210 211 return property(**locals()) 212 213 @apply
214 - def length():
215 doc =\ 216 """ Length in bytes of the data part of the query. C{unsigned int} stored in 4 bytes at byte 12. """ 217 def fget(self): 218 return self.unpack(start=12, fmt=DWORD)[0]
219 220 def fset(self, val): 221 self.pack(val, start=12, fmt=DWORD) 222 223 return property(**locals()) 224 225 @apply
226 - def data():
227 doc =\ 228 """ 229 The data part of this command. Returned/set as/by a TransferBuffer. Stored at byte 16. 230 231 Setting it by default changes self.length to the length of the new buffer. You may have to reset it to 232 the significant part of the buffer. You would normally use the C{command} property of L{ShortCommand} or L{LongCommand} instead. 233 """ 234 def fget(self): 235 return self[16:]
236 237 def fset(self, buffer): 238 self[16:] = buffer 239 self.length = len(buffer) 240 241 return property(**locals()) 242 243
244 -class ShortCommand(Command):
245 246 """ A L{Command} whoose data section is 4 bytes long """ 247 248 SIZE = 20 #: Packet size in bytes 249
250 - def __init__(self, number=0x00, type=0x00, command=0x00):
251 """ 252 @param number: L{Command.number} 253 @param type: L{Command.type} 254 @param command: L{ShortCommand.command} 255 """ 256 Command.__init__(self, ShortCommand.SIZE) 257 self.number = number 258 self.type = type 259 self.length = 4 260 self.command = command
261 262 @apply
263 - def command():
264 doc =\ 265 """ The command. Not sure why this is needed in addition to Command.number. C{unsigned int} 4 bytes long at byte 16. """ 266 def fget(self): 267 return self.unpack(start=16, fmt=DWORD)[0]
268 269 def fset(self, val): 270 self.pack(val, start=16, fmt=DWORD)
271 272 return property(**locals()) 273
274 -class DirOpen(Command):
275 276 """ Open a directory for reading its contents """ 277 NUMBER = 0x33 #: Command number 278
279 - def __init__(self, path):
280 Command.__init__(self, 20 + len(path)) 281 self.number=DirOpen.NUMBER 282 self.type = 0x01 283 self.length = 4 + len(path) 284 self.path_length = len(path) 285 self.path = path
286 287 @apply
288 - def path_length():
289 doc =\ 290 """ The length in bytes of the path to follow. C{unsigned int} stored at byte 16. """ 291 def fget(self): 292 return self.unpack(start=16, fmt=DWORD)[0]
293 294 def fset(self, val): 295 self.pack(val, start=16, fmt=DWORD) 296 297 return property(**locals()) 298 299 @apply
300 - def path():
301 doc =\ 302 """ The path. Stored as a string at byte 20. """ 303 304 def fget(self): 305 return self.unpack(start=20, fmt="<"+str(self.path_length)+"s")[0]
306 307 def fset(self, val): 308 self.pack(val, start=20, fmt="<"+str(self.path_length)+"s") 309 310 return property(**locals()) 311
312 -class DirRead(ShortCommand):
313 """ The command that asks the device to send the next item in the list """ 314 NUMBER = 0x35 #: Command number
315 - def __init__(self, id):
316 """ @param id: The identifier returned as a result of a L{DirOpen} command """ 317 ShortCommand.__init__(self, number=DirRead.NUMBER, type=0x01, command=id)
318
319 -class DirClose(ShortCommand):
320 """ Close a previously opened directory """ 321 NUMBER = 0x34 #: Command number
322 - def __init__(self, id):
323 """ @param id: The identifier returned as a result of a L{DirOpen} command """ 324 ShortCommand.__init__(self, number=DirClose.NUMBER, type=0x01, command=id)
325 326
327 -class LongCommand(Command):
328 329 """ A L{Command} whoose data section is 16 bytes long """ 330 331 SIZE = 32 #: Size in bytes of C{LongCommand} packets 332
333 - def __init__(self, number=0x00, type=0x00, command=0x00):
334 """ 335 @param number: L{Command.number} 336 @param type: L{Command.type} 337 @param command: L{LongCommand.command} 338 """ 339 Command.__init__(self, LongCommand.SIZE) 340 self.number = number 341 self.type = type 342 self.length = 16 343 self.command = command
344 345 @apply
346 - def command():
347 doc =\ 348 """ 349 The command. Not sure why it is needed in addition to L{Command.number}. 350 It is a list of C{unsigned integers} of length between 1 and 4. 4 C{unsigned int} stored in 16 bytes at byte 16. 351 """ 352 def fget(self): 353 return self.unpack(start=16, fmt="<"+str(self.length/4)+"I")
354 355 def fset(self, val): 356 if "__len__" not in dir(val): val = (val,) 357 start = 16 358 for command in val: 359 self.pack(command, start=start, fmt=DWORD) 360 start += struct.calcsize(DWORD)
361 362 return property(**locals()) 363 364
365 -class AcknowledgeBulkRead(LongCommand):
366 367 """ Must be sent to device after a bulk read """ 368
369 - def __init__(self, bulk_read_id):
370 """ bulk_read_id is an integer, the id of the bulk read we are acknowledging. See L{Answer.id} """ 371 LongCommand.__init__(self, number=0x1000, type=0x00, command=bulk_read_id)
372
373 -class DeviceInfoQuery(Command):
374 """ The command used to ask for device information """ 375 NUMBER=0x0101 #: Command number
376 - def __init__(self):
377 Command.__init__(self, 16) 378 self.number=DeviceInfoQuery.NUMBER 379 self.type=0x01
380
381 -class FileClose(ShortCommand):
382 """ File close command """ 383 NUMBER = 0x11 #: Command number
384 - def __init__(self, id):
386
387 -class FileOpen(Command):
388 """ File open command """ 389 NUMBER = 0x10 390 READ = 0x00 391 WRITE = 0x01
392 - def __init__(self, path, mode=0x00):
393 Command.__init__(self, 24 + len(path)) 394 self.number=FileOpen.NUMBER 395 self.type = 0x01 396 self.length = 8 + len(path) 397 self.mode = mode 398 self.path_length = len(path) 399 self.path = path
400 401 @apply
402 - def mode():
403 doc =\ 404 """ The file open mode. Is either L{FileOpen.READ} or L{FileOpen.WRITE}. C{unsigned int} stored at byte 16. """ 405 def fget(self): 406 return self.unpack(start=16, fmt=DWORD)[0]
407 408 def fset(self, val): 409 self.pack(val, start=16, fmt=DWORD)
410 411 return property(**locals()) 412 413 @apply
414 - def path_length():
415 doc =\ 416 """ The length in bytes of the path to follow. C{unsigned int} stored at byte 20. """ 417 def fget(self): 418 return self.unpack(start=20, fmt=DWORD)[0]
419 420 def fset(self, val): 421 self.pack(val, start=20, fmt=DWORD) 422 423 return property(**locals()) 424 425 @apply
426 - def path():
427 doc =\ 428 """ The path. Stored as a string at byte 24. """ 429 430 def fget(self): 431 return self.unpack(start=24, fmt="<"+str(self.path_length)+"s")[0]
432 433 def fset(self, val): 434 self.pack(val, start=24, fmt="<"+str(self.path_length)+"s") 435 436 return property(**locals()) 437
438 -class FileRead(Command):
439 """ Command to read from an open file """ 440 NUMBER = 0x16 #: Command number to read from a file
441 - def __init__(self, id, offset, size):
442 """ 443 @param id: File identifier returned by a L{FileOpen} command 444 @type id: C{unsigned int} 445 @param offset: Position in file at which to read 446 @type offset: C{unsigned long long} 447 @param size: number of bytes to read 448 @type size: C{unsigned int} 449 """ 450 Command.__init__(self, 32) 451 self.number=FileRead.NUMBER 452 self.type = 0x01 453 self.length = 32 454 self.id = id 455 self.offset = offset 456 self.size = size
457 458 @apply
459 - def id():
460 doc =\ 461 """ The file ID returned by a FileOpen command. C{unsigned int} stored in 4 bytes at byte 16. """ 462 def fget(self): 463 return self.unpack(start=16, fmt=DWORD)[0]
464 465 def fset(self, val): 466 self.pack(val, start=16, fmt=DWORD)
467 468 return property(**locals()) 469 470 @apply
471 - def offset():
472 doc =\ 473 """ offset in the file at which to read. C{unsigned long long} stored in 8 bytes at byte 20. """ 474 def fget(self): 475 return self.unpack(start=20, fmt=DDWORD)[0]
476 477 def fset(self, val): 478 self.pack(val, start=20, fmt=DDWORD) 479 480 return property(**locals()) 481 482 @apply
483 - def size():
484 doc =\ 485 """ The number of bytes to read. C{unsigned int} stored in 4 bytes at byte 28. """ 486 def fget(self): 487 return self.unpack(start=28, fmt=DWORD)[0]
488 489 def fset(self, val): 490 self.pack(val, start=28, fmt=DWORD) 491 492 return property(**locals()) 493 494 495 496
497 -class PathQuery(Command):
498 499 """ 500 Defines structure of command that requests information about a path 501 502 >>> print prstypes.PathQuery("/test/path/", number=prstypes.PathQuery.PROPERTIES) 503 1800 0000 0100 0000 0000 0000 0f00 0000 ................ 504 0b00 0000 2f74 6573 742f 7061 7468 2f ..../test/path/ 505 """ 506 NUMBER = 0x18 #: Command number 507
508 - def __init__(self, path):
509 Command.__init__(self, 20 + len(path)) 510 self.number=PathQuery.NUMBER 511 self.type = 0x01 512 self.length = 4 + len(path) 513 self.path_length = len(path) 514 self.path = path
515 516 @apply
517 - def path_length():
518 doc =\ 519 """ The length in bytes of the path to follow. C{unsigned int} stored at byte 16. """ 520 def fget(self): 521 return self.unpack(start=16, fmt=DWORD)[0]
522 523 def fset(self, val): 524 self.pack(val, start=16, fmt=DWORD) 525 526 return property(**locals()) 527 528 @apply
529 - def path():
530 doc =\ 531 """ The path. Stored as a string at byte 20. """ 532 533 def fget(self): 534 return self.unpack(start=20, fmt="<"+str(self.path_length)+"s")[0]
535 536 def fset(self, val): 537 self.pack(val, start=20, fmt="<"+str(self.path_length)+"s") 538 539 return property(**locals()) 540 541
542 -class Response(Command):
543 """ 544 Defines the structure of response packets received from the device. 545 546 C{Response} inherits from C{Command} as the first 16 bytes have the same structure. 547 """ 548 549 SIZE = 32 #: Size of response packets in the SONY protocol 550
551 - def __init__(self, packet):
552 """ C{len(packet) == Response.SIZE} """ 553 if len(packet) != Response.SIZE: 554 raise PacketError(str(self.__class__)[7:-2] + " packets must have exactly " + str(Response.SIZE) + " bytes not " + str(len(packet))) 555 Command.__init__(self, packet) 556 if self.number != 0x00001000: 557 raise PacketError("Response packets must have their number set to " + hex(0x00001000))
558 559 @apply
560 - def rnumber():
561 doc =\ 562 """ 563 The response number. C{unsigned int} stored in 4 bytes at byte 16. 564 565 It will be the command number from a command that was sent to the device sometime before this response. 566 """ 567 def fget(self): 568 return self.unpack(start=16, fmt=DWORD)[0]
569 570 def fset(self, val): 571 self.pack(val, start=16, fmt=DWORD)
572 573 return property(**locals()) 574 575 @apply
576 - def data():
577 doc =\ 578 """ The last 3 DWORDs (12 bytes) of data in this response packet. Returned as a list of unsigned integers. """ 579 def fget(self): 580 return self.unpack(start=20, fmt="<III")
581 582 def fset(self, val): 583 self.pack(val, start=20, fmt="<III") 584 585 return property(**locals()) 586
587 -class ListResponse(Response):
588 589 """ Defines the structure of response packets received during list (ll) queries. See L{PathQuery}. """ 590 591 IS_FILE = 0xffffffd2 #: Queried path is a file 592 IS_INVALID = 0xfffffff9 #: Queried path is malformed/invalid 593 IS_UNMOUNTED = 0xffffffc8 #: Queried path is not mounted (i.e. a removed storage card/stick) 594 IS_EOL = 0xfffffffa #: There are no more entries in the list 595 PATH_NOT_FOUND = 0xffffffd7 #: Queried path is not found 596 597 @apply
598 - def code():
599 doc =\ 600 """ The response code. Used to indicate conditions like EOL/Error/IsFile etc. C{unsigned int} stored in 4 bytes at byte 20. """ 601 def fget(self): 602 return self.unpack(start=20, fmt=DDWORD)[0]
603 604 def fset(self, val): 605 self.pack(val, start=20, fmt=DDWORD)
606 607 return property(**locals()) 608 609 @apply
610 - def is_file():
611 """ True iff queried path is a file """ 612 def fget(self): 613 return self.code == ListResponse.IS_FILE
614 return property(**locals()) 615 616 @apply
617 - def is_invalid():
618 """ True iff queried path is invalid """ 619 def fget(self): 620 return self.code == ListResponse.IS_INVALID
621 return property(**locals()) 622 623 @apply
624 - def path_not_found():
625 """ True iff queried path is not found """ 626 def fget(self): 627 return self.code == ListResponse.PATH_NOT_FOUND
628 return property(**locals()) 629 630 @apply
631 - def is_unmounted():
632 """ True iff queried path is unmounted (i.e. removed storage card) """ 633 def fget(self): 634 return self.code == ListResponse.IS_UNMOUNTED
635 return property(**locals()) 636 637 @apply
638 - def is_eol():
639 """ True iff there are no more items in the list """ 640 def fget(self): 641 return self.code == ListResponse.IS_EOL
642 return property(**locals()) 643
644 -class Answer(TransferBuffer):
645 """ Defines the structure of packets sent to host via a bulk transfer (i.e., bulk reads) """ 646
647 - def __init__(self, packet):
648 """ @param packet: C{len(packet)} S{>=} C{16} """ 649 if len(packet) < 16 : raise PacketError(str(self.__class__)[7:-2] + " packets must have a length of atleast 16 bytes") 650 TransferBuffer.__init__(self, packet)
651 652 @apply
653 - def id():
654 doc =\ 655 """ The id of this bulk transfer packet. C{unsigned int} stored in 4 bytes at byte 0. """ 656 657 def fget(self): 658 return self.unpack(start=0, fmt=DWORD)[0]
659 660 def fset(self, val): 661 self.pack(val, start=0, fmt=DWORD)
662 663 return property(**locals()) 664
665 -class FileProperties(Answer):
666 667 """ Defines the structure of packets that contain size, date and permissions information about files/directories. """ 668 669 @apply
670 - def file_size():
671 doc =\ 672 """ The file size. C{unsigned long long} stored in 8 bytes at byte 16. """ 673 674 def fget(self): 675 return self.unpack(start=16, fmt=DDWORD)[0]
676 677 def fset(self, val): 678 self.pack(val, start=16, fmt=DDWORD)
679 680 return property(**locals()) 681 682 @apply
683 - def is_dir():
684 doc =\ 685 """ 686 True if path points to a directory, False if it points to a file. C{unsigned int} stored in 4 bytes at byte 24. 687 688 Value of 1 == file and 2 == dir 689 """ 690 691 def fget(self): 692 return (self.unpack(start=24, fmt=DWORD)[0] == 2)
693 694 def fset(self, val): 695 if val: val = 2 696 else: val = 1 697 self.pack(val, start=24, fmt=DWORD) 698 699 return property(**locals()) 700 701 @apply
702 - def ctime():
703 doc =\ 704 """ The creation time of this file/dir as an epoch (seconds since Jan 1970). C{unsigned int} stored in 4 bytes at byte 28. """ 705 706 def fget(self): 707 return self.unpack(start=28, fmt=DWORD)[0]
708 709 def fset(self, val): 710 self.pack(val, start=28, fmt=DWORD) 711 712 return property(**locals()) 713 714 @apply
715 - def wtime():
716 doc =\ 717 """ The modification time of this file/dir as an epoch (seconds since Jan 1970). C{unsigned int} stored in 4 bytes at byte 32""" 718 719 def fget(self): 720 return self.unpack(start=32, fmt=DWORD)[0]
721 722 def fset(self, val): 723 self.pack(val, start=32, fmt=DWORD) 724 725 return property(**locals()) 726 727 @apply
728 - def is_readonly():
729 doc =\ 730 """ 731 Whether this file is readonly. C{unsigned int} stored in 4 bytes at byte 36. 732 733 A value of 0 corresponds to read/write and 4 corresponds to read-only. The device doesn't send full permissions information. 734 """ 735 736 def fget(self): 737 return self.unpack(start=36, fmt=DWORD)[0] != 0
738 739 def fset(self, val): 740 if val: val = 4 741 else: val = 0 742 self.pack(val, start=36, fmt=DWORD) 743 744 return property(**locals()) 745
746 -class IdAnswer(Answer):
747 748 """ Defines the structure of packets that contain identifiers for queries. """ 749 750 @apply
751 - def id():
752 doc =\ 753 """ The identifier. C{unsigned int} stored in 4 bytes at byte 16. Should be sent in commands asking for the next item in the list. """ 754 755 def fget(self): 756 return self.unpack(start=16, fmt=DWORD)[0]
757 758 def fset(self, val): 759 self.pack(val, start=16, fmt=DWORD)
760 761 return property(**locals()) 762
763 -class DeviceInfo(Answer):
764 """ Defines the structure of the packet containing information about the device """ 765 766 @apply
767 - def device_name():
768 """ The name of the device. Stored as a string in 32 bytes starting at byte 16. """ 769 def fget(self): 770 src = self.unpack(start=16, fmt="<32s")[0] 771 return src[0:src.find('\x00')]
772 return property(**locals())
773 774 @apply
775 - def device_version():
776 """ The device version. Stored as a string in 32 bytes starting at byte 48. """ 777 def fget(self): 778 src = self.unpack(start=48, fmt="<32s")[0] 779 return src[0:src.find('\x00')]
780 return property(**locals()) 781 782 @apply
783 - def software_version():
784 """ Version of the software on the device. Stored as a string in 26 bytes starting at byte 80. """ 785 def fget(self): 786 src = self.unpack(start=80, fmt="<26s")[0] 787 return src[0:src.find('\x00')]
788 return property(**locals()) 789 790 @apply
791 - def mime_type():
792 """ Mime type served by tinyhttp?. Stored as a string in 32 bytes starting at byte 104. """ 793 def fget(self): 794 src = self.unpack(start=104, fmt="<32s")[0] 795 return src[0:src.find('\x00')]
796 return property(**locals()) 797
798 -class ListAnswer(Answer):
799 800 """ Defines the structure of packets that contain items in a list. """ 801 802 @apply
803 - def is_dir():
804 doc =\ 805 """ True if list item points to a directory, False if it points to a file. C{unsigned int} stored in 4 bytes at byte 16. """ 806 807 def fget(self): 808 return (self.unpack(start=16, fmt=DWORD)[0] == 2)
809 810 def fset(self, val): 811 if val: val = 2 812 else: val = 1 813 self.pack(val, start=16, fmt=DWORD)
814 815 return property(**locals()) 816 817 @apply
818 - def name_length():
819 doc =\ 820 """ The length in bytes of the list item to follow. C{unsigned int} stored in 4 bytes at byte 20 """ 821 def fget(self): 822 return self.unpack(start=20, fmt=DWORD)[0]
823 824 def fset(self, val): 825 self.pack(val, start=20, fmt=DWORD) 826 827 return property(**locals()) 828 829 @apply
830 - def name():
831 doc =\ 832 """ The name of the list item. Stored as an (ascii?) string at byte 24. """ 833 834 def fget(self): 835 return self.unpack(start=24, fmt="<"+str(self.name_length)+"s")[0]
836 837 def fset(self, val): 838 self.pack(val, start=24, fmt="<"+str(self.name_length)+"s") 839 840 return property(**locals()) 841