diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | INSTALL | 17 | ||||
-rw-r--r-- | logs/mtp-detect-cowon-iaudio-u3.txt | 260 | ||||
-rw-r--r-- | src/libmtp.c | 20 | ||||
-rw-r--r-- | src/libusb-glue.c | 6 | ||||
-rw-r--r-- | src/libusb-glue.h | 9 | ||||
-rw-r--r-- | src/unicode.c | 30 | ||||
-rw-r--r-- | src/unicode.h | 1 |
8 files changed, 350 insertions, 3 deletions
@@ -1,3 +1,13 @@ +2007-08-24 Linus Walleij <triad@df.lth.se> + + * src/libusb-glue.h: new device flag to strip all non-7bit chars from + filenames on some lame devices. + * src/libusb-glue.c: tag the Philips Shoqbox with this flag. + * src/libmtp.c: strip the non-7bit chars from filenames if that + flag is set. + * src/unicode.h: introduce a 7bit-strip helper function. + * src/unicode.c: dito. + 2007-08-22 Linus Walleij <triad@df.lth.se> * src/libmtp.c: deal with setting of metadata sets for u16/u32:s that @@ -168,3 +168,20 @@ has write access on /proc/bus/usb/* You can find the Linux hotplug project at: http://linux-hotplug.sourceforge.net/ + + +Compilation for embedded devices +-------------------------------- + +Problems with Autoconf complaining about a missing malloc() function +during cross-compilation can be solved with this hack if you're using +glibc: + + % export ac_cv_func_malloc_0_nonnull=yes + % ./configure + +If you're using uclibc you may have to smack in a custom rpl_malloc() +function in your program, see the Autoconf texinfo documentation. + +See further: +http://wiki.buici.com/wiki/Autoconf_and_RPL_MALLOC
\ No newline at end of file diff --git a/logs/mtp-detect-cowon-iaudio-u3.txt b/logs/mtp-detect-cowon-iaudio-u3.txt new file mode 100644 index 0000000..6ed4629 --- /dev/null +++ b/logs/mtp-detect-cowon-iaudio-u3.txt @@ -0,0 +1,260 @@ +libmtp version: 0.2.1 + +Attempting to connect device(s) +Detect: Successfully connected 1 devices +USB low-level info: + Using kernel interface "usbfs" + bcdUSB: 512 + bDeviceClass: 0 + bDeviceSubClass: 0 + bDeviceProtocol: 0 + idVendor: 0e21 + idProduct: 0701 + IN endpoint maxpacket: 64 bytes + OUT endpoint maxpacket: 64 bytes + Device flags: 0x00000000 +Device info: + Manufacturer: COWON SYSTEMS, Inc. + Model: iAUDIO U3 + Device version: + Serial number: 070709180728009DC10000E04CC34BD9 + Vendor extension ID: 0x00000006 + Vendor extension description: microsoft.com/WMDRMPD: 10.1;audible.com: 1.0; +Supported operations: + 1001: get device info + 1002: Open session + 1003: Close session + 1004: Get storage IDs + 1005: Get storage info + 1006: Get number of objects + 1007: Get object handles + 1008: Get object info + 1009: Get object + 100b: Delete object + 100c: Send object info + 100d: Send object + 100f: Format storage + 1010: Reset device + 1014: Get device property description + 1015: Get device property value + 1016: Set device property value + 1017: Reset device property value + 9810: Get object references + 9811: Set object references + 9802: Get object property description + 9801: Get object properties supported + 9803: Get object property value + 9804: Set object property value + 9805: Get object property list + 9806: Set object property list + 101b: Get partial object + 9101: Get secure time challenge + 9102: Get secure time response + 9103: Set license response + 9104: Get sync list + 9105: Send meter challenge query + 9106: Get meter challenge + 9107: Get meter response + 9108: Clean data store + 9109: Get license state + 910a: Send WMDRM-PD Command + 910b: Send WMDRM-PD Request +Events supported: + None. +Device Properties Supported: + 0x5001: Battery Level + 0xd401: Synchronization Partner + 0xd402: Device Friendly Name + 0xd101: Secure Time + 0xd102: Device Certificate +Playable File (Object) Types and Object Properties Supported: + 3009: MP3 + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + dc8b: Track UINT16 data type ANY 16BIT VALUE form GET/SET + de9a: AudioBitRate UINT32 data type range: MIN 8000, MAX 320000, STEP 1 READ ONLY + dc46: Artist STRING data type GET/SET + dc8c: Genre STRING data type GET/SET + de93: SampleRate UINT32 data type range: MIN 8000, MAX 48000, STEP 50 READ ONLY + de94: NumberOfChannels UINT16 data type enumeration: 1, 2, READ ONLY + dc9a: AlbumName STRING data type GET/SET + dc89: Duration UINT32 data type ANY 32BIT VALUE form GET/SET + de99: AudioWAVECodec UINT32 data type enumeration: 0, 1, 2, 3, 8, 9, 11, 49, 50, 80, 85, 352, 353, 354, 355, 356, 41222, GET/SET + dc99: OriginalReleaseDate STRING data type GET/SET + b901: WMA + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + dc8b: Track UINT16 data type ANY 16BIT VALUE form GET/SET + de9a: AudioBitRate UINT32 data type range: MIN 5000, MAX 320000, STEP 1 READ ONLY + dc46: Artist STRING data type GET/SET + dc8c: Genre STRING data type GET/SET + de93: SampleRate UINT32 data type range: MIN 8000, MAX 48000, STEP 50 READ ONLY + de94: NumberOfChannels UINT16 data type enumeration: 1, 2, READ ONLY + dc9a: AlbumName STRING data type GET/SET + dc89: Duration UINT32 data type ANY 32BIT VALUE form GET/SET + de99: AudioWAVECodec UINT32 data type enumeration: 0, 1, 2, 3, 8, 9, 11, 49, 50, 80, 85, 352, 353, 354, 355, 356, 41222, GET/SET + dc99: OriginalReleaseDate STRING data type GET/SET + 3801: JPEG + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + 300a: MS AVI + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + 3001: Association/Directory + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + ba05: Abstract Audio Video Playlist + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + 3000: Undefined Type + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + b802: Firmware + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + ba03: Abstract Audio Album + dc97: EffectiveRating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc8a: Rating UINT16 data type range: MIN 0, MAX 100, STEP 1 GET/SET + dc44: Name STRING data type GET/SET + dc01: StorageID UINT32 data type ANY 32BIT VALUE form READ ONLY + dc04: ObjectSize UINT64 data type READ ONLY + dc07: ObjectFileName STRING data type GET/SET + dc09: DateModified STRING data type GET/SET + dc4f: NonConsumable UINT8 data type enumeration: 0, 1, GET/SET + dc02: ObjectFormat UINT16 data type ANY 16BIT VALUE form READ ONLY + dc0b: ParentObject UINT32 data type ANY 32BIT VALUE form READ ONLY + dc41: PersistantUniqueObjectIdentifier UINT128 data type READ ONLY + dc03: ProtectionStatus UINT16 data type enumeration: 0, 1, READ ONLY + dc86: RepresentativeSampleData array of UINT8 data type ANY 8BIT VALUE form GET/SET + dc81: RepresentativeSampleFormat UINT16 data type enumeration: 14337, READ ONLY + dc83: RepresentativeSampleHeight UINT32 data type range: MIN 0, MAX 1000000, STEP 1 READ ONLY + dc84: RepresentativeSampleWidth UINT32 data type range: MIN 0, MAX 1000000, STEP 1 READ ONLY + dc46: Artist STRING data type GET/SET + dc8c: Genre STRING data type GET/SET +Storage Devices: + StorageID: 0x00010001 + StorageType: 0x0003 + FilesystemType: 0x0002 + AccessCapability: 0x0000 + MaxCapacity: 1998856192 + FreeSpaceInBytes: 1909501789 + FreeSpaceInObjects: 3463 + StorageDescription: Internal Storage + VolumeIdentifier: 070709180728009DC10000E04CC34BD9 +Special directories: + Default music folder: 0x00000000 + Default playlist folder: 0x00000000 + Default picture folder: 0x00000000 + Default video folder: 0x00000000 + Default organizer folder: 0x00000000 + Default zencast folder: 0x00000000 + Default album folder: 0x00000000 + Default text folder: 0x00000000 +MTP-specific device properties: + Friendly name: iAUDIO U3 + Synchronization partner: Longhorn Sync Engine + Battery level 100 of 100 (100%) +libmtp supported (playable) filetypes: + ISO MPEG-1 Audio Layer 3 + Microsoft Windows Media Audio + JPEG file + Audio Video Interleave + Firmware file + +Secure Time: +<DRMCLOCK type="status"><VALUE>#20050214 +21:55:58Z#</VALUE><FLAG>DRM_CLK_NEEDS_REFRESH</FLAG></DRMCLOCK>AG></DRMCLOCK> + +Device Certificate: +<DEVCERT version="1.0"><CERTIFICATE type="DEVICE"><DATA><UNIQUEID +private="1">BwcJGAcoAJ3BAADgTMNL2QAAAAA=</UNIQUEID><PUBLICKEY +private="1">vfDhBXaNQlRRG9V5abU1/R9SpHrjc86jupyGALap5seg4jzOPxGVUw==</PUBLICKEY><KEYDATA>1vX7YOqtS1Lk9Wlmmf/wqZGHtFc=</KEYDATA></DATA><MSDRM_SIGNATURE_VALUE>pbyIv5wY9kKwgq4FwJfu+7DEelOM3PTbAe62illRcG+gR7ak+xKVGQ==</MSDRM_SIGNATURE_VALUE><SYMSIGNATURE>DexHP/w29hVmYtDW4IsxKRLiMNk=</SYMSIGNATURE></CERTIFICATE><FALLBACK><SECURITYVERSION>2.4.102.169</SECURITYVERSION><CERTIFICATE +private="1">vfDhBXaNQlRRG9V5abU1/R9SpHrjc86jupyGALap5seg4jzOPxGVUwIEZqlU4PbfqA5uknmVVe6QWGzKbu9KXKnl+lLy5PzubzdMQB+1Q7gVEB5K</CERTIFICATE></FALLBACK><CERTIFICATE +type="GROUP"><DATA><NAME>iAudio U3 MTP</NAME><MANUFACTURER>COWON +Systems, Inc.</MANUFACTURER><MAKE>COWON Systems, +Inc.</MAKE><DISTRIBUTOR>COWON Systems, Inc.</DISTRIBUTOR><MODEL>iAudio +U3</MODEL><SECURITYLEVEL>2000</SECURITYLEVEL><HARDWARE_VER_MAJOR>1</HARDWARE_VER_MAJOR><HARDWARE_VER_MINOR>3</HARDWARE_VER_MINOR><FIRMWARE_VER_MAJOR>1</FIRMWARE_VER_MAJOR><FIRMWARE_VER_MINOR>2</FIRMWARE_VER_MINOR><FEATURES><CLOCK>2</CLOCK><SECURECLOCK><URL>http://go.microsoft.com/fwlink/?LinkId=25817</URL><PUBLICKEY>!CNhvvz1WaNV1AFUmetxkvm9iD4UrE9cnGUi!qcqdxMiXmD1*ikYGA==</PUBLICKEY></SECURECLOCK><METERING>1</METERING><LICENSE_ACQ>1</LICENSE_ACQ><LICENSE_SYNC>1</LICENSE_SYNC><ENCRYPTION>1</ENCRYPTION><SYMMETRIC_OPT>1</SYMMETRIC_OPT></FEATURES><LIMITS><MAXCHAINDEPTH>2</MAXCHAINDEPTH><MAXLICENSESIZE>10240</MAXLICENSESIZE><MAXHEADERSIZE>5120</MAXHEADERSIZE></LIMITS><PUBLICKEY>Ap4rKQEBTuHQZBBcYMqOgcraBkqKHTUXl8pbRIx+quIq0aLccpXZXA==</PUBLICKEY></DATA><MSDRM_SIGNATURE_VALUE>hUe6hoIHQ8Ub6S10Sf7QJQxBfxwWbatdyxZADUvnav5ghZLNv4J9Rg==</MSDRM_SIGNATURE_VALUE></CERTIFICATE><CERTIFICATE +type="AUTHORIZATION"><DATA><SECURITYLEVEL>2000</SECURITYLEVEL><AUTH_ID>525</AUTH_ID><PUBLICKEY>+hVWeQQEOLQH8QxQghdd5Cnb1zcHSQR2HLVlTTInXNFKBkSn9bC4Mg==</PUBLICKEY></DATA><MSDRM_SIGNATURE_VALUE>cXGlAjnUI7m/AFKFGx/zGf8SYyge+bGSW2S5NwkuBnCRJkDUcpY5XQ==</MSDRM_SIGNATURE_VALUE></CERTIFICATE><CERTIFICATE +type="AUTHORIZATION_ROOT"><DATA><AUTH_ID>1</AUTH_ID><PUBLICKEY>a1t3hxrg!qbOgktnbYaEEi4teCse!gz6RvTPuC!zizKJlpU7xoduSw==</PUBLICKEY></DATA><MSDRM_SIGNATURE_VALUE>y7C+qgiwu/FP5YRSXzf6vJAv4Tb06hv+Y8IC9z2tnA362aLhpY9MSQ==</MSDRM_SIGNATURE_VALUE></CERTIFICATE></DEVCERT> +WMPInfo.xml Does not exist on this device +OK. diff --git a/src/libmtp.c b/src/libmtp.c index 96106e7..40af5c6 100644 --- a/src/libmtp.c +++ b/src/libmtp.c @@ -3946,8 +3946,12 @@ int LIBMTP_Send_File_From_File_Descriptor(LIBMTP_mtpdevice_t *device, prop->ObjectHandle = filedata->item_id; prop->property = PTP_OPC_ObjectFileName; prop->datatype = PTP_DTC_STR; - if (filedata->filename != NULL) + if (filedata->filename != NULL) { prop->propval.str = strdup(filedata->filename); + if (ptp_usb->device_flags & DEVICE_FLAG_ONLY_7BIT_FILENAMES) { + strip_7bit_from_utf8(prop->propval.str); + } + } proplist = add_mtp_prop_to_proplist(proplist, prop); break; case PTP_OPC_ProtectionStatus: @@ -4001,6 +4005,9 @@ int LIBMTP_Send_File_From_File_Descriptor(LIBMTP_mtpdevice_t *device, memset(&new_file, 0, sizeof(PTPObjectInfo)); new_file.Filename = filedata->filename; + if (ptp_usb->device_flags & DEVICE_FLAG_ONLY_7BIT_FILENAMES) { + strip_7bit_from_utf8(new_file.Filename); + } if (filedata->filesize == (uint64_t) -1) { // This is a stream. Set a dummy length... new_file.ObjectCompressedSize = 1; @@ -4691,6 +4698,7 @@ LIBMTP_folder_t *LIBMTP_Get_Folder_List(LIBMTP_mtpdevice_t *device) uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name, uint32_t parent_id) { PTPParams *params = (PTPParams *) device->params; + PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo; uint32_t parenthandle = 0; uint32_t store = get_first_storageid(device); PTPObjectInfo new_folder; @@ -4699,6 +4707,9 @@ uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name, uint32_t p memset(&new_folder, 0, sizeof(new_folder)); new_folder.Filename = name; + if (ptp_usb->device_flags & DEVICE_FLAG_ONLY_7BIT_FILENAMES) { + strip_7bit_from_utf8(new_folder.Filename); + } new_folder.ObjectCompressedSize = 1; new_folder.ObjectFormat = PTP_OFC_Association; new_folder.ParentObject = parent_id; @@ -4935,6 +4946,7 @@ static int create_new_abstract_list(LIBMTP_mtpdevice_t *device, uint32_t localph = parenthandle; uint8_t nonconsumable = 0x00U; /* By default it is consumable */ PTPParams *params = (PTPParams *) device->params; + PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo; char fname[256]; uint8_t data[2]; @@ -4991,6 +5003,9 @@ static int create_new_abstract_list(LIBMTP_mtpdevice_t *device, prop->property = PTP_OPC_ObjectFileName; prop->datatype = PTP_DTC_STR; prop->propval.str = strdup(fname); + if (ptp_usb->device_flags & DEVICE_FLAG_ONLY_7BIT_FILENAMES) { + strip_7bit_from_utf8(prop->propval.str); + } proplist = add_mtp_prop_to_proplist(proplist, prop); break; case PTP_OPC_ProtectionStatus: @@ -5070,6 +5085,9 @@ static int create_new_abstract_list(LIBMTP_mtpdevice_t *device, PTPObjectInfo new_object; new_object.Filename = fname; + if (ptp_usb->device_flags & DEVICE_FLAG_ONLY_7BIT_FILENAMES) { + strip_7bit_from_utf8(new_object.Filename); + } new_object.ObjectCompressedSize = 1; new_object.ObjectFormat = objectformat; diff --git a/src/libusb-glue.c b/src/libusb-glue.c index 3565f1c..0d7af3e 100644 --- a/src/libusb-glue.c +++ b/src/libusb-glue.c @@ -162,7 +162,7 @@ static const LIBMTP_device_entry_t mtp_device_table[] = { // From Gerhard Mekenkamp { "Philips GoGear Audio", 0x0471, 0x0165, DEVICE_FLAG_NONE }, // from David Holm <wormie@alberg.dk> - { "Philips Shoqbox", 0x0471, 0x0172, DEVICE_FLAG_NONE }, + { "Philips Shoqbox", 0x0471, 0x0172, DEVICE_FLAG_ONLY_7BIT_FILENAMES }, // from npedrosa { "Philips PSA610", 0x0471, 0x0181, DEVICE_FLAG_NONE }, // From libgphoto2 source @@ -390,10 +390,12 @@ static const LIBMTP_device_entry_t mtp_device_table[] = { * Cowon Systems, Inc. * The iAudio audiophile devices don't encourage the use of MTP. */ + // Reported by Patrik Johansson <Patrik.Johansson@qivalue.com> + {"Cowon iAudio U3 (MTP mode)", 0x0e21, 0x0701, DEVICE_FLAG_NONE }, // Reported by Roberth Karman {"Cowon iAudio 7 (MTP mode)", 0x0e21, 0x0751, DEVICE_FLAG_NONE }, // Reported by TJ Something <tjbk_tjb@users.sourceforge.net> - {"Cowon D2 (MTP mode)", 0x0e21, 0x0801, DEVICE_FLAG_NONE }, + {"Cowon iAudio D2 (MTP mode)", 0x0e21, 0x0801, DEVICE_FLAG_NONE }, /* * Insignia, dual-mode. diff --git a/src/libusb-glue.h b/src/libusb-glue.h index abf43c6..7a77d04 100644 --- a/src/libusb-glue.h +++ b/src/libusb-glue.h @@ -98,6 +98,15 @@ * filename extension will be done for files of "unknown" type. */ #define DEVICE_FLAG_IRIVER_OGG_ALZHEIMER 0x00000010 +/** + * This flag indicates a limitation in the filenames a device + * can accept - they must be 7 bit (all chars <= 127/0x7F). + * It was found first on the Philips Shoqbox, and is a deviation + * from the PTP standard which mandates that any unicode chars + * may be used for filenames. I guess this is caused by a 7bit-only + * filesystem being used intrinsically on the device. + */ +#define DEVICE_FLAG_ONLY_7BIT_FILENAMES 0x00000020 /** * Internal USB struct. diff --git a/src/unicode.c b/src/unicode.c index 8b87c70..c1859ba 100644 --- a/src/unicode.c +++ b/src/unicode.c @@ -94,3 +94,33 @@ char *utf16_to_utf8(LIBMTP_mtpdevice_t *device, const uint16_t *unicstr) } return strdup(loclstr); } + +/** + * This helper function simply removes any consecutive chars + * > 0x7F and replace then with an underscore. In UTF-8 + * consequtive chars > 0x7F represent one single character so + * it has to be done like this (and it's elegant). It will only + * shrink the string in size so no copying is needed. + */ +void strip_7bit_from_utf8(char *str) +{ + int i,j,k; + i = 0; + j = 0; + k = strlen(str); + while (i < k) { + if ((uint8_t) str[i] > 0x7FU) { + str[j] = '_'; + // Skip over any consequtive > 0x7F chars. + while((uint8_t) str[i] > 0x7FU) { + i++; + } + } else { + str[j] = str[i]; + i++; + } + j++; + } + // Terminate stripped string... + str[j] = '\0'; +} diff --git a/src/unicode.h b/src/unicode.h index 1655c76..30e98ba 100644 --- a/src/unicode.h +++ b/src/unicode.h @@ -36,5 +36,6 @@ int ucs2_strlen(uint16_t const * const); char *utf16_to_utf8(LIBMTP_mtpdevice_t*,const uint16_t*); +void strip_7bit_from_utf8(char *str); #endif /* __MTP__UNICODE__H */ |