139
139
}
140
140
141
141
# Storage IDs struct
142
+ _MTP_STORAGE_ID = const (0x00010001 )
143
+
142
144
_MTP_STORAGE_IDS_DESC = {
143
145
"count" : 0 | uctypes .UINT32 ,
144
146
"storage_ids" : (4 | uctypes .ARRAY , 1 | uctypes .UINT32 ) # Variable length array
@@ -199,7 +201,7 @@ def __init__(self, storage_path="/", rx_size=_DEFAULT_RX_BUF_SIZE, tx_size=_DEFA
199
201
200
202
# Filesystem attributes
201
203
self ._storage_path = storage_path
202
- self ._storage_id = 0x00010001 # Fixed ID for the single storage we support
204
+ self ._storage_id = _MTP_STORAGE_ID # Fixed ID for the single storage we support
203
205
self ._next_object_handle = 0x00000001 # Start object handles at 1
204
206
self ._object_handles = {} # Maps object handles to file paths
205
207
self ._parent_map = {} # Maps handles to parent handles
@@ -226,6 +228,8 @@ def _log(self, msg, *args):
226
228
def desc_cfg (self , desc , itf_num , ep_num , strs ):
227
229
"""Build the USB configuration descriptor for this interface."""
228
230
self ._log ("Building descriptors: itf_num={}, ep_num={}" , itf_num , ep_num )
231
+
232
+ # Add the interface identifier to the strings
229
233
i_interface = len (strs )
230
234
strs .append ("MTP" )
231
235
@@ -535,22 +539,24 @@ def _cmd_get_device_info(self):
535
539
# Handle variable-length data after the fixed struct
536
540
offset = 8 # Start after the fixed part of the struct
537
541
542
+
538
543
# MTP extensions description string - Microsoft extension
539
544
# MTP extension strings are ASCII strings in PIMA format (8-bit length + 8-bit chars with null terminator)
540
- ext_string = "microsoft.com: 1.0" # Standard Microsoft extension string
545
+ offset += self ._write_mtp_string (data , offset , "microsoft.com: 1.0" )
546
+ # ext_string = "microsoft.com: 1.0" # Standard Microsoft extension string
541
547
542
- # String length (8-bit, including null terminator)
543
- data [offset ] = len (ext_string ) + 1
544
- offset += 1
548
+ # # String length (8-bit, including null terminator)
549
+ # data[offset] = len(ext_string) * 2 + 1
550
+ # offset += 1
545
551
546
- # String data as ASCII
547
- for c in ext_string :
548
- data [offset ] = ord (c )
549
- offset += 1
552
+ # # String data as ASCII
553
+ # for c in ext_string:
554
+ # data[offset] = ord(c)
555
+ # offset += 1
550
556
551
- # ASCII null terminator
552
- data [offset ] = 0
553
- offset += 1
557
+ # # ASCII null terminator
558
+ # data[offset] = 0
559
+ # offset += 1
554
560
555
561
# Functional mode
556
562
struct .pack_into ("<H" , data , offset , 0 ) # Standard mode
@@ -573,25 +579,25 @@ def _cmd_get_device_info(self):
573
579
]
574
580
575
581
# Number of operations
576
- struct .pack_into ("<H " , data , offset , len (operations ))
577
- offset += 2
582
+ struct .pack_into ("<I " , data , offset , len (operations ))
583
+ offset += 4
578
584
579
585
# List of operation codes
580
586
for op in operations :
581
587
struct .pack_into ("<H" , data , offset , op )
582
588
offset += 2
583
589
584
590
# Supported events (array of event codes) - empty for now
585
- struct .pack_into ("<H " , data , offset , 0 ) # No events supported
586
- offset += 2
591
+ struct .pack_into ("<I " , data , offset , 0 ) # No events supported
592
+ offset += 4
587
593
588
594
# Supported device properties - empty for now
589
- struct .pack_into ("<H " , data , offset , 0 ) # No device properties
590
- offset += 2
595
+ struct .pack_into ("<I " , data , offset , 0 ) # No device properties
596
+ offset += 4
591
597
592
598
# Supported capture formats - empty for now
593
- struct .pack_into ("<H " , data , offset , 0 ) # No capture formats
594
- offset += 2
599
+ struct .pack_into ("<I " , data , offset , 0 ) # No capture formats
600
+ offset += 4
595
601
596
602
# Supported playback formats (file formats we support)
597
603
formats = [
@@ -601,8 +607,8 @@ def _cmd_get_device_info(self):
601
607
]
602
608
603
609
# Number of formats
604
- struct .pack_into ("<H " , data , offset , len (formats ))
605
- offset += 2
610
+ struct .pack_into ("<I " , data , offset , len (formats ))
611
+ offset += 4
606
612
607
613
# List of format codes
608
614
for fmt in formats :
@@ -710,7 +716,7 @@ def _cmd_get_storage_info(self, params):
710
716
storage_info = uctypes .struct (uctypes .addressof (data ), _MTP_STORAGE_INFO_DESC , uctypes .LITTLE_ENDIAN )
711
717
712
718
# Fill in the fixed fields
713
- storage_info .storage_type = _MTP_STORAGE_FIXED_RAM
719
+ storage_info .storage_type = _MTP_STORAGE_FIXED_MEDIA
714
720
storage_info .filesystem_type = 0x0002 # Generic hierarchical
715
721
storage_info .access_capability = _MTP_STORAGE_READ_WRITE # Read-write access
716
722
storage_info .max_capacity = total_bytes
@@ -765,13 +771,18 @@ def _cmd_get_object_handles(self, params):
765
771
parent_handle = params [2 ] if len (params ) > 2 else 0
766
772
767
773
if storage_id != 0xFFFFFFFF and storage_id != self ._storage_id :
774
+ self ._log ("Error invalid storage id: {}" , storage_id )
768
775
self ._send_response (_MTP_RESPONSE_INVALID_STORAGE_ID )
769
776
return
770
777
771
778
# Collect filtered handles
772
779
handles = []
780
+ self ._log ("get handles: {} {} {}" , storage_id , format_code , parent_handle )
781
+ self ._log ("handles: {}" , self ._object_handles )
782
+ self ._log ("parent: {}" , self ._parent_map )
783
+
773
784
for handle , parent in self ._parent_map .items ():
774
- if (parent_handle == 0 or parent == parent_handle ) and handle in self ._object_handles :
785
+ if (parent_handle in ( 0 , 0xFFFFFFFF ) or parent == parent_handle ) and handle in self ._object_handles :
775
786
# Apply format filter if specified
776
787
if format_code == 0 or self ._get_format_by_path (self ._object_handles [handle ]) == format_code :
777
788
handles .append (handle )
@@ -830,7 +841,7 @@ def _cmd_get_object_info(self, params):
830
841
# Get filename (basename of the path)
831
842
parts = filepath .split ('/' )
832
843
filename = parts [- 1 ] if parts [- 1 ] else parts [- 2 ] # Handle trailing slash for dirs
833
-
844
+ self . _log ( '***** filename {}' , filename )
834
845
# Prepare object info dataset
835
846
data = bytearray (256 )
836
847
offset = 0
@@ -847,9 +858,9 @@ def _cmd_get_object_info(self, params):
847
858
struct .pack_into ("<H" , data , offset , 0 )
848
859
offset += 2
849
860
850
- # Object size (in bytes)
851
- struct .pack_into ("<I" , data , offset , filesize )
852
- offset += 4
861
+ # # Object size (in bytes)
862
+ # struct.pack_into("<I", data, offset, filesize)
863
+ # offset += 4
853
864
854
865
# Object compressed size (same as size)
855
866
struct .pack_into ("<I" , data , offset , filesize )
@@ -1385,12 +1396,14 @@ def _write_mtp_string(self, buffer, offset, string):
1385
1396
"""
1386
1397
if not string :
1387
1398
# Empty string - just write a 0 length
1388
- struct .pack_into ("<H " , buffer , offset , 0 )
1389
- return 2
1399
+ struct .pack_into ("<B " , buffer , offset , 0 )
1400
+ return 1
1390
1401
1391
- # String length in 16-bit characters (including null terminator)
1392
- struct .pack_into ("<H" , buffer , offset , len (string ) + 1 )
1393
- offset += 2
1402
+ start = offset
1403
+
1404
+ # String length in 8-bit characters (including null terminator)
1405
+ struct .pack_into ("<B" , buffer , offset , len (string ) + 1 )
1406
+ offset += 1
1394
1407
1395
1408
# String data (each character as 16-bit Unicode)
1396
1409
# Use little-endian UTF-16 encoding with BOM (Byte Order Mark)
@@ -1404,7 +1417,7 @@ def _write_mtp_string(self, buffer, offset, string):
1404
1417
offset += 2
1405
1418
1406
1419
# Return total bytes written
1407
- return 2 + (len (string ) + 1 ) * 2
1420
+ return offset - start # 2 + (len(string) + 1) * 2
1408
1421
1409
1422
def _format_timestamp (self , timestamp ):
1410
1423
"""Format a timestamp into MTP date string format."""
0 commit comments