libusb1-glue.c revision aac75024bc25550ffdb4df95299e453842a0abab
1fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* 2fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * \file libusb1-glue.c 3fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Low-level USB interface glue towards libusb. 4fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 5fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Copyright (C) 2005-2007 Richard A. Low <richard@wentnet.com> 67433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij * Copyright (C) 2005-2012 Linus Walleij <triad@df.lth.se> 7bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * Copyright (C) 2006-2012 Marcus Meissner 8fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Copyright (C) 2007 Ted Bullock 9fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Copyright (C) 2008 Chris Bagwell <chris@cnpbagwell.com> 10fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 11fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This library is free software; you can redistribute it and/or 12fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * modify it under the terms of the GNU Lesser General Public 13fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * License as published by the Free Software Foundation; either 14fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * version 2 of the License, or (at your option) any later version. 15fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 16fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This library is distributed in the hope that it will be useful, 17fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * but WITHOUT ANY WARRANTY; without even the implied warranty of 18fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Lesser General Public License for more details. 20fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 21fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * You should have received a copy of the GNU Lesser General Public 22fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * License along with this library; if not, write to the 23fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 24fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Boston, MA 02111-1307, USA. 25fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 26fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Created by Richard Low on 24/12/2005. (as mtp-utils.c) 27fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Modified by Linus Walleij 2006-03-06 28fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * (Notice that Anglo-Saxons use little-endian dates and Swedes 29fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * use big-endian dates.) 30fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 31fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 32b9a840cc79bb96f135fe4abd4248881240026112Yingxi Yu#include "config.h" 33b9a840cc79bb96f135fe4abd4248881240026112Yingxi Yu#include "libmtp.h" 34b9a840cc79bb96f135fe4abd4248881240026112Yingxi Yu#include "libusb-glue.h" 35b9a840cc79bb96f135fe4abd4248881240026112Yingxi Yu#include "device-flags.h" 36b9a840cc79bb96f135fe4abd4248881240026112Yingxi Yu#include "util.h" 37b9a840cc79bb96f135fe4abd4248881240026112Yingxi Yu#include "ptp.h" 381165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner 391165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner#include <errno.h> 401165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner#include <stdio.h> 411165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner#include <stdlib.h> 421165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner#include <string.h> 431165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner#include <unistd.h> 441165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner 45fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#include "ptp-pack.c" 46fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 47fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* 48fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Default USB timeout length. This can be overridden as needed 49fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * but should start with a reasonable value so most common 50fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * requests can be completed. The original value of 4000 was 51fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * not long enough for large file transfer. Also, players can 52fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * spend a bit of time collecting data. Higher values also 53fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * make connecting/disconnecting more reliable. 54fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 55fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define USB_TIMEOUT_DEFAULT 20000 56fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define USB_TIMEOUT_LONG 60000 57fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic inline int get_timeout(PTP_USB* ptp_usb) 58fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 59fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_LONG_TIMEOUT(ptp_usb)) { 60fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return USB_TIMEOUT_LONG; 61fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 62fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return USB_TIMEOUT_DEFAULT; 63fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 64fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 65fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* USB Feature selector HALT */ 66fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#ifndef USB_FEATURE_HALT 67fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define USB_FEATURE_HALT 0x00 68fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#endif 69fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 70fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* Internal data types */ 71fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstruct mtpdevice_list_struct { 72fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *device; 73fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPParams *params; 74fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb; 75fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint32_t bus_location; 76fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct mtpdevice_list_struct *next; 77fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij}; 78fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijtypedef struct mtpdevice_list_struct mtpdevice_list_t; 79fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 80fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic const LIBMTP_device_entry_t mtp_device_table[] = { 81fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* We include an .h file which is shared between us and libgphoto2 */ 82fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#include "music-players.h" 83fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij}; 8411cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic const int mtp_device_table_size = 8511cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij sizeof(mtp_device_table) / sizeof(LIBMTP_device_entry_t); 86fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 87fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij// Local functions 883df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhangstatic LIBMTP_error_number_t init_usb(); 89fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void close_usb(PTP_USB* ptp_usb); 90fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int find_interface_and_endpoints(libusb_device *dev, 9115d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *conf, 92fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t *interface, 9315d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *altsetting, 94fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep, 95fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep_maxpacket, 96fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* outep, 97fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* outep_maxpacket, 98fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* intep); 99fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void clear_stall(PTP_USB* ptp_usb); 10011cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic int init_ptp_usb(PTPParams* params, 10111cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij PTP_USB* ptp_usb, libusb_device* dev); 10211cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic short ptp_write_func(unsigned long, 10311cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij PTPDataHandler*, void *data, unsigned long*); 10411cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic short ptp_read_func (unsigned long, 10511cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij PTPDataHandler*, void *data, unsigned long*, int); 10611cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic int usb_get_endpoint_status(PTP_USB* ptp_usb, 10711cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij int ep, uint16_t* status); 108fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 109fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 110fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Get a list of the supported USB devices. 111fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 112fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * The developers depend on users of this library to constantly 113fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * add in to the list of supported devices. What we need is the 114fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * device name, USB Vendor ID (VID) and USB Product ID (PID). 115fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * put this into a bug ticket at the project homepage, please. 116fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * The VID/PID is used to let e.g. udev lift the device to 117fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * console userspace access when it's plugged in. 118fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 119fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param devices a pointer to a pointer that will hold a device 120fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * list after the call to this function, if it was 121fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * successful. 122fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param numdevs a pointer to an integer that will hold the number 123fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of devices in the device list if the call was successful. 124fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 0 if the list was successfull retrieved, any other 125fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * value means failure. 126fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 12711cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijint LIBMTP_Get_Supported_Devices_List(LIBMTP_device_entry_t ** const devices, 12811cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij int * const numdevs) 129fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 130fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = (LIBMTP_device_entry_t *) &mtp_device_table; 131fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = mtp_device_table_size; 132fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 133fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 134fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 135fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1363df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhangstatic LIBMTP_error_number_t init_usb() 137fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 138468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner static int libusb1_initialized = 0; 139468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner 140fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 141fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Some additional libusb debugging please. 142fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We use the same level debug between MTP and USB. 143fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 144468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner if (libusb1_initialized) 145468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner return LIBMTP_ERROR_NONE; 146468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner 1473df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (libusb_init(NULL) < 0) { 1483df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_ERROR("Libusb1 init failed\n"); 1493df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return LIBMTP_ERROR_USB_LAYER; 1503df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang } 151fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 152468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner libusb1_initialized = 1; 153468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner 154fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((LIBMTP_debug & LIBMTP_DEBUG_USB) != 0) 155fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_set_debug(NULL,9); 1563df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return LIBMTP_ERROR_NONE; 157fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 158fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 159fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 16011cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * Small recursive function to append a new usb_device to the linked 16111cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * list of USB MTP devices 16211cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * @param devlist dynamic linked list of pointers to usb devices with 16311cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * MTP properties, to be extended with new device. 164fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param newdevice the new device to add. 165fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param bus_location bus for this device. 166fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return an extended array or NULL on failure. 167fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 168fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic mtpdevice_list_t *append_to_mtpdevice_list(mtpdevice_list_t *devlist, 169fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *newdevice, 170fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint32_t bus_location) 171fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 172fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *new_list_entry; 173fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 174fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry = (mtpdevice_list_t *) malloc(sizeof(mtpdevice_list_t)); 175fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (new_list_entry == NULL) { 176fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return NULL; 177fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 178fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Fill in USB device, if we *HAVE* to make a copy of the device do it here. 179fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry->device = newdevice; 180fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry->bus_location = bus_location; 181fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry->next = NULL; 182fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 183fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (devlist == NULL) { 184fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return new_list_entry; 185fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 186fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *tmp = devlist; 187fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (tmp->next != NULL) { 188fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tmp = tmp->next; 189fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 190fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tmp->next = new_list_entry; 191fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 192fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return devlist; 193fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 194fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 195fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 196fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Small recursive function to free dynamic memory allocated to the linked list 197fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of USB MTP devices 198fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param devlist dynamic linked list of pointers to usb devices with MTP 199fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * properties. 200fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return nothing 201fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 202fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void free_mtpdevice_list(mtpdevice_list_t *devlist) 203fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 204fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *tmplist = devlist; 205fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 206fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (devlist == NULL) 207fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return; 208fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (tmplist != NULL) { 209fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *tmp = tmplist; 210fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tmplist = tmplist->next; 211fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Do not free() the fields (ptp_usb, params)! These are used elsewhere. 212fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free(tmp); 213fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 214fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return; 215fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 216fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 217fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 218fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This checks if a device has an MTP descriptor. The descriptor was 219fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * elaborated about in gPhoto bug 1482084, and some official documentation 220fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * with no strings attached was published by Microsoft at 221fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://www.microsoft.com/whdc/system/bus/USB/USBFAQ_intermed.mspx#E3HAC 222fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 223fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param dev a device struct from libusb. 224fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param dumpfile set to non-NULL to make the descriptors dump out 225fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to this file in human-readable hex so we can scruitinze them. 226fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 1 if the device is MTP compliant, 0 if not. 227fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 228fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int probe_device_descriptor(libusb_device *dev, FILE *dumpfile) 229fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 230fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device_handle *devh; 231fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char buf[1024], cmd; 232fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i; 233fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 234fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* This is to indicate if we find some vendor interface */ 235fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_vendor_spec_interface = 0; 236fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 237fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 238fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_device_descriptor (dev, &desc); 239fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) return 0; 240fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 241fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Don't examine devices that are not likely to 242fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * contain any MTP interface, update this the day 243fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * you find some weird combination... 244fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 24526ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (!(desc.bDeviceClass == LIBUSB_CLASS_PER_INTERFACE || 24626ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij desc.bDeviceClass == LIBUSB_CLASS_COMM || 24726ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij desc.bDeviceClass == LIBUSB_CLASS_PTP || 248fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.bDeviceClass == 0xEF || /* Intf. Association Desc.*/ 24926ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij desc.bDeviceClass == LIBUSB_CLASS_VENDOR_SPEC)) { 250fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 251fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 252fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 253bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij /* 254bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * Attempt to open Device on this port 255bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * 256bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * TODO: is there a way to check the number of endpoints etc WITHOUT 257bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * opening the device? Some color calibration devices are REALLY 258bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * sensitive to this, and I found a Canon custom scanner that doesn't 259bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * like it at all either :-( 260bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij */ 261fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_open(dev, &devh); 262fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 263fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Could not open this device */ 264fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 265fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 266fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 267fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 268fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Loop over the device configurations and interfaces. Nokia MTP-capable 269fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * handsets (possibly others) typically have the string "MTP" in their 270fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * MTP interface descriptions, that's how they can be detected, before 271fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * we try the more esoteric "OS descriptors" (below). 272fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 273fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < desc.bNumConfigurations; i++) { 274fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t j; 275fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_config_descriptor *config; 276fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 277fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_config_descriptor (dev, i, &config); 278fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 279fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("configdescriptor %d get failed with ret %d in probe_device_descriptor yet dev->descriptor.bNumConfigurations > 0\n", i, ret); 280fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 281fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 282fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 283fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (j = 0; j < config->bNumInterfaces; j++) { 284fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int k; 285fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (k = 0; k < config->interface[j].num_altsetting; k++) { 286fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Current interface descriptor */ 287fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij const struct libusb_interface_descriptor *intf = 288fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &config->interface[j].altsetting[k]; 289fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 290fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 291fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * MTP interfaces have three endpoints, two bulk and one 292fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * interrupt. Don't probe anything else. 293fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 294fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (intf->bNumEndpoints != 3) 295fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 296fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 297fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 298fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We only want to probe for the OS descriptor if the 29926ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij * device is LIBUSB_CLASS_VENDOR_SPEC or one of the interfaces 300fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * in it is, so flag if we find an interface like this. 301fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 30226ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (intf->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC) { 303fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found_vendor_spec_interface = 1; 304fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 305fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 306fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 30711cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * TODO: Check for Still Image Capture class with PIMA 15740 30811cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * protocol, also known as PTP 309fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 310fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#if 0 31126ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (intf->bInterfaceClass == LIBUSB_CLASS_PTP 312fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij && intf->bInterfaceSubClass == 0x01 313fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij && intf->bInterfaceProtocol == 0x01) { 314fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL) { 31515d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(dumpfile, "Configuration %d, interface %d, altsetting %d:\n", i, j, k); 316fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, " Found PTP device, check vendor " 317fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "extension...\n"); 318fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 319bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij /* 320bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * This is where we may insert code to open a PTP 321bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * session and query the vendor extension ID to see 322bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * if it is 0xffffffff, i.e. MTP according to the spec. 323bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij */ 324fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (was_mtp_extension) { 325fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 326fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 327fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 328fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 329fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#endif 330fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 331fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 332fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Next we search for the MTP substring in the interface name. 333fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * For example : "RIM MS/MTP" should work. 334fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 335fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf[0] = '\0'; 336fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_string_descriptor_ascii(devh, 337fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij config->interface[j].altsetting[k].iInterface, 338fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf, 339fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1024); 340fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < 3) 341fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 342fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (strstr((char *) buf, "MTP") != NULL) { 343fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL) { 344fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Configuration %d, interface %d, altsetting %d:\n", i, j, k); 345fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, " Interface description contains the string \"MTP\"\n"); 346fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, " Device recognized as MTP, no further probing.\n"); 347fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 34815d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 349fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 350fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 351fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 352fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (libusb_kernel_driver_active(devh, config->interface[j].altsetting[k].iInterface)) 353fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 354fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 355fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Specifically avoid probing anything else than USB mass storage devices 356fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * and non-associated drivers in Linux. 357fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 35826ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (config->interface[j].altsetting[k].bInterfaceClass != 35926ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij LIBUSB_CLASS_MASS_STORAGE) { 360fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("avoid probing device using attached kernel interface\n"); 36115d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 362be4a1b25d1bf8df0f9ae15d7aa0a89d2877120cdLinus Walleij libusb_close(devh); 363fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 364fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 365fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 366fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 36715d18e31458be5006eb229df68869df2fff93495Linus Walleij } 36815d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 36915d18e31458be5006eb229df68869df2fff93495Linus Walleij } 370fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 371fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 372fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Only probe for OS descriptor if the device is vendor specific 373fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * or one of the interfaces found is. 374fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 37526ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (desc.bDeviceClass == LIBUSB_CLASS_VENDOR_SPEC || 376fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found_vendor_spec_interface) { 377fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 378fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Read the special descriptor */ 379fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_descriptor(devh, 0x03, 0xee, buf, sizeof(buf)); 380fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 381fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 382fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * If something failed we're probably stalled to we need 383fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to clear the stall off the endpoint and say this is not 384fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * MTP. 385fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 386fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < 0) { 387fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* EP0 is the default control endpoint */ 3881165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner libusb_clear_halt (devh, 0); 389fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 390fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 391fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 392fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 393fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Dump it, if requested 394fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL && ret > 0) { 395fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Microsoft device descriptor 0xee:\n"); 396fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij data_dump_ascii(dumpfile, buf, ret, 16); 397fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 398fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 399fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if descriptor length is at least 10 bytes */ 400fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < 10) { 401fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 402fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 403fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 404fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 405fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if this device has a Microsoft Descriptor */ 406fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!((buf[2] == 'M') && (buf[4] == 'S') && 407fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (buf[6] == 'F') && (buf[8] == 'T'))) { 408fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 409fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 410fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 411fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 412fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if device responds to control message 1 or if there is an error */ 413fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij cmd = buf[16]; 414fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer (devh, 415fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR, 416fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij cmd, 417fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 418fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 4, 419fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf, 420fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(buf), 421fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij USB_TIMEOUT_DEFAULT); 422fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 423fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Dump it, if requested 424fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL && ret > 0) { 425fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Microsoft device response to control message 1, CMD 0x%02x:\n", cmd); 426fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij data_dump_ascii(dumpfile, buf, ret, 16); 427fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 428fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 429fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If this is true, the device either isn't MTP or there was an error */ 430fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret <= 0x15) { 431fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* TODO: If there was an error, flag it and let the user know somehow */ 432fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* if(ret == -1) {} */ 433fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 434fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 435fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 436fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 437fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if device is MTP or if it is something like a USB Mass Storage 438fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij device with Janus DRM support */ 439fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) { 440fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 441fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 442fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 443fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 444fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* After this point we are probably dealing with an MTP device */ 445fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 446fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 447fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Check if device responds to control message 2, which is 448fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * the extended device parameters. Most devices will just 449fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * respond with a copy of the same message as for the first 450fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * message, some respond with zero-length (which is OK) 451fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * and some with pure garbage. We're not parsing the result 452fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * so this is not very important. 453fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 454fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer (devh, 455fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR, 456fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij cmd, 457fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 458fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 5, 459fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf, 460fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(buf), 461fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij USB_TIMEOUT_DEFAULT); 462fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 463fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Dump it, if requested 464fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL && ret > 0) { 465fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Microsoft device response to control message 2, CMD 0x%02x:\n", cmd); 466fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij data_dump_ascii(dumpfile, buf, ret, 16); 467fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 468fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 469fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If this is true, the device errored against control message 2 */ 470fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret == -1) { 471fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* TODO: Implement callback function to let managing program know there 472fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij was a problem, along with description of the problem */ 473fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("Potential MTP Device with VendorID:%04x and " 474fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "ProductID:%04x encountered an error responding to " 475fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "control message 2.\n" 476fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "Problems may arrise but continuing\n", 477fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idVendor, desc.idProduct); 478fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (dumpfile != NULL && ret == 0) { 479fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Zero-length response to control message 2 (OK)\n"); 480fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (dumpfile != NULL) { 481fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Device responds to control message 2 with some data.\n"); 482fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 483fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Close the USB device handle */ 484fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 485fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 486fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 487fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 488fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Close the USB device handle */ 489fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 490fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 491fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 492fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 493fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 494fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This function scans through the connected usb devices on a machine and 495fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * if they match known Vendor and Product identifiers appends them to the 496fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * dynamic array mtp_device_list. Be sure to call 497fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * <code>free_mtpdevice_list(mtp_device_list)</code> when you are done 498fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * with it, assuming it is not NULL. 499fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param mtp_device_list dynamic array of pointers to usb devices with MTP 500fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * properties (if this list is not empty, new entries will be appended 501fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to the list). 502fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return LIBMTP_ERROR_NONE implies that devices have been found, scan the list 503fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * appropriately. LIBMTP_ERROR_NO_DEVICE_ATTACHED implies that no 504fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * devices have been found. 505fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 506fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic LIBMTP_error_number_t get_mtp_usb_device_list(mtpdevice_list_t ** mtp_device_list) 507fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 508fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ssize_t nrofdevs; 509fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device **devs = NULL; 510fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret, i; 5113df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_error_number_t init_usb_ret; 512fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 5133df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang init_usb_ret = init_usb(); 5143df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (init_usb_ret != LIBMTP_ERROR_NONE) 5153df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return init_usb_ret; 516fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 517fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij nrofdevs = libusb_get_device_list (NULL, &devs); 518fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < nrofdevs ; i++) { 519fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *dev = devs[i]; 520fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 521fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 522fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_device_descriptor(dev, &desc); 523fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) continue; 524fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 52526ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (desc.bDeviceClass != LIBUSB_CLASS_HUB) { 526fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i; 527fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found = 0; 528fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 529fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // First check if we know about the device already. 530fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Devices well known to us will not have their descriptors 531fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // probed, it caused problems with some devices. 532fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for(i = 0; i < mtp_device_table_size; i++) { 533fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(desc.idVendor == mtp_device_table[i].vendor_id && 534fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct == mtp_device_table[i].product_id) { 535fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Append this usb device to the MTP device list */ 536fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *mtp_device_list = append_to_mtpdevice_list(*mtp_device_list, 537fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev, 538fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_bus_number(dev)); 539fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found = 1; 540fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 541fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 542fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 543fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // If we didn't know it, try probing the "OS Descriptor". 544fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!found) { 545fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (probe_device_descriptor(dev, NULL)) { 546fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Append this usb device to the MTP USB Device List */ 547fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *mtp_device_list = append_to_mtpdevice_list(*mtp_device_list, 548fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev, 549fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_bus_number(dev)); 550fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 551fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 552fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * By thomas_-_s: Also append devices that are no MTP but PTP devices 553fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * if this is commented out. 554fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 555fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 556fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else { 557fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Check whether the device is no USB hub but a PTP. 55826ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if ( dev->config != NULL &&dev->config->interface->altsetting->bInterfaceClass == LIBUSB_CLASS_PTP && dev->descriptor.bDeviceClass != LIBUSB_CLASS_HUB ) { 559fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *mtp_device_list = append_to_mtpdevice_list(*mtp_device_list, dev, bus->location); 560fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 561fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 562fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 563fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 564fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 565fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 5661e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 567fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 568fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If nothing was found we end up here. */ 569fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(*mtp_device_list == NULL) { 570fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NO_DEVICE_ATTACHED; 571fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 572fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 573fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 574fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 575fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 576fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Checks if a specific device with a certain bus and device 577fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * number has an MTP type device descriptor. 578fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 579fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param busno the bus number of the device to check 580fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param deviceno the device number of the device to check 581fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 1 if the device is MTP else 0 582fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 583fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijint LIBMTP_Check_Specific_Device(int busno, int devno) 584fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 585fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ssize_t nrofdevs; 586fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device **devs = NULL; 587fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i; 5883df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_error_number_t init_usb_ret; 589fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 5903df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang init_usb_ret = init_usb(); 5913df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (init_usb_ret != LIBMTP_ERROR_NONE) 5923df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return 0; 593fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 594fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij nrofdevs = libusb_get_device_list (NULL, &devs); 595fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < nrofdevs ; i++ ) { 59630f9acdc94c087209d3feb80bf545ce3cf1033a0Jonas Salling 59730f9acdc94c087209d3feb80bf545ce3cf1033a0Jonas Salling if (libusb_get_bus_number(devs[i]) != busno) 598fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 59930f9acdc94c087209d3feb80bf545ce3cf1033a0Jonas Salling if (libusb_get_device_address(devs[i]) != devno) 600fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 60130f9acdc94c087209d3feb80bf545ce3cf1033a0Jonas Salling 602fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (probe_device_descriptor(devs[i], NULL)) 603fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 604fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 605fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 606fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 607fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 608fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 609fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Detect the raw MTP device descriptors and return a list of 610fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of the devices found. 611fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 612fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param devices a pointer to a variable that will hold 613fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * the list of raw devices found. This may be NULL 614fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * on return if the number of detected devices is zero. 615fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * The user shall simply <code>free()</code> this 616fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * variable when finished with the raw devices, 617fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * in order to release memory. 618fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param numdevs a pointer to an integer that will hold 619fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * the number of devices in the list. This may 620fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * be 0. 621fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 0 if successful, any other value means failure. 622fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 623fbbef8b16876568f760986e4ff8f4921b8373fd5Linus WalleijLIBMTP_error_number_t LIBMTP_Detect_Raw_Devices(LIBMTP_raw_device_t ** devices, 624fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int * numdevs) 625fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 626fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *devlist = NULL; 627fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *dev; 628fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_error_number_t ret; 629fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_raw_device_t *retdevs; 630fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int devs = 0; 631fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i, j; 632fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 633fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = get_mtp_usb_device_list(&devlist); 634fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret == LIBMTP_ERROR_NO_DEVICE_ATTACHED) { 635fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = NULL; 636fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = 0; 637fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 638fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (ret != LIBMTP_ERROR_NONE) { 639fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: get_mtp_usb_device_list() " 640fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "error code: %d on line %d\n", ret, __LINE__); 641fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 642fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 643fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 644fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Get list size 645fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = devlist; 646fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (dev != NULL) { 647fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij devs++; 648fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = dev->next; 649fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 650fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (devs == 0) { 651fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = NULL; 652fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = 0; 653fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 654fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 655fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Conjure a device list 656fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs = (LIBMTP_raw_device_t *) malloc(sizeof(LIBMTP_raw_device_t) * devs); 657fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (retdevs == NULL) { 658fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Out of memory 659fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = NULL; 660fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = 0; 661fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_MEMORY_ALLOCATION; 662fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 663fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = devlist; 664fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij i = 0; 665fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (dev != NULL) { 666fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int device_known = 0; 667fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 668fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 669fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_device_descriptor (dev->device, &desc); 670fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Assign default device info 671fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.vendor = NULL; 672fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.vendor_id = desc.idVendor; 673fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.product = NULL; 674fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.product_id = desc.idProduct; 675fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.device_flags = 0x00000000U; 676fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // See if we can locate some additional vendor info and device flags 677fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for(j = 0; j < mtp_device_table_size; j++) { 678fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(desc.idVendor == mtp_device_table[j].vendor_id && 679fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct == mtp_device_table[j].product_id) { 680fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij device_known = 1; 681fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.vendor = mtp_device_table[j].vendor; 682fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.product = mtp_device_table[j].product; 683fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.device_flags = mtp_device_table[j].device_flags; 684fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 685fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This device is known to the developers 686fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("Device %d (VID=%04x and PID=%04x) is a %s %s.\n", 687fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij i, 688fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idVendor, 689fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct, 690fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtp_device_table[j].vendor, 691fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtp_device_table[j].product); 692fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 693fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 694fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 695fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!device_known) { 696524e42caee22313738733a3e4ee74acdb5e561b7Andrés G. Aragoneses device_unknown(i, desc.idVendor, desc.idProduct); 697fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 698fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Save the location on the bus 699fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].bus_location = libusb_get_bus_number (dev->device); 700fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].devnum = libusb_get_device_address (dev->device); 701fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij i++; 702fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = dev->next; 703fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 704fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = retdevs; 705fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = i; 706fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free_mtpdevice_list(devlist); 707fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 708fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 709fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 710fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 711fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This routine just dumps out low-level 712fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * USB information about the current device. 713fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param ptp_usb the USB device to get information from. 714fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 715fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid dump_usbinfo(PTP_USB *ptp_usb) 716fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 717fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *dev; 718fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 719fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 720fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (libusb_kernel_driver_active(ptp_usb->handle, ptp_usb->interface)) 721fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Interface has a kernel driver attached.\n"); 722fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 723fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = libusb_get_device (ptp_usb->handle); 724fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_device_descriptor (dev, &desc); 725fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 726fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bcdUSB: %d\n", desc.bcdUSB); 727fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bDeviceClass: %d\n", desc.bDeviceClass); 728fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bDeviceSubClass: %d\n", desc.bDeviceSubClass); 729fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bDeviceProtocol: %d\n", desc.bDeviceProtocol); 730fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" idVendor: %04x\n", desc.idVendor); 731fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" idProduct: %04x\n", desc.idProduct); 732fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" IN endpoint maxpacket: %d bytes\n", ptp_usb->inep_maxpacket); 733fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" OUT endpoint maxpacket: %d bytes\n", ptp_usb->outep_maxpacket); 734fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Raw device info:\n"); 735fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Bus location: %d\n", ptp_usb->rawdevice.bus_location); 736fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Device number: %d\n", ptp_usb->rawdevice.devnum); 737fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Device entry info:\n"); 738fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Vendor: %s\n", ptp_usb->rawdevice.device_entry.vendor); 739fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Vendor id: 0x%04x\n", ptp_usb->rawdevice.device_entry.vendor_id); 740fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Product: %s\n", ptp_usb->rawdevice.device_entry.product); 741fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Vendor id: 0x%04x\n", ptp_usb->rawdevice.device_entry.product_id); 742fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Device flags: 0x%08x\n", ptp_usb->rawdevice.device_entry.device_flags); 743fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (void) probe_device_descriptor(dev, stdout); 744fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 745fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 746fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 747fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Retrieve the apropriate playlist extension for this 748fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * device. Rather hacky at the moment. This is probably 749fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * desired by the managing software, but when creating 750fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * lists on the device itself you notice certain preferences. 751fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param ptp_usb the USB device to get suggestion for. 752fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return the suggested playlist extension. 753fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 754fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijconst char *get_playlist_extension(PTP_USB *ptp_usb) 755fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 756fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *dev; 757fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 758fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij static char creative_pl_extension[] = ".zpl"; 759fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij static char default_pl_extension[] = ".pla"; 760fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 761fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = libusb_get_device(ptp_usb->handle); 762fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_device_descriptor (dev, &desc); 763fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (desc.idVendor == 0x041e) 764fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return creative_pl_extension; 765fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return default_pl_extension; 766fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 767fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 768fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void 769fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijlibusb_glue_debug (PTPParams *params, const char *format, ...) 770fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 771fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_list args; 772fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 773fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_start (args, format); 774fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->debug_func!=NULL) 775fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->debug_func (params->data, format, args); 776fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 777fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 778fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij vfprintf (stderr, format, args); 779fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf (stderr,"\n"); 780fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fflush (stderr); 781fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 782fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_end (args); 783fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 784fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 785fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void 786fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijlibusb_glue_error (PTPParams *params, const char *format, ...) 787fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 788fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_list args; 789fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 790fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_start (args, format); 791fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->error_func!=NULL) 792fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->error_func (params->data, format, args); 793fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 794fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 795fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij vfprintf (stderr, format, args); 796fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf (stderr,"\n"); 797fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fflush (stderr); 798fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 799fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_end (args); 800fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 801fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 802fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 803fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* 804fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * ptp_read_func() and ptp_write_func() are 805fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * based on same functions usb.c in libgphoto2. 806fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Much reading packet logs and having fun with trials and errors 807fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * reveals that WMP / Windows is probably using an algorithm like this 808fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * for large transfers: 809fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 810fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 1. Send the command (0x0c bytes) if headers are split, else, send 811fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * command plus sizeof(endpoint) - 0x0c bytes. 812fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 2. Send first packet, max size to be sizeof(endpoint) but only when using 813fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * split headers. Else goto 3. 814fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 3. REPEAT send 0x10000 byte chunks UNTIL remaining bytes < 0x10000 815fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We call 0x10000 CONTEXT_BLOCK_SIZE. 816fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 4. Send remaining bytes MOD sizeof(endpoint) 817fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 5. Send remaining bytes. If this happens to be exactly sizeof(endpoint) 818fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * then also send a zero-length package. 819fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 820fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Further there is some special quirks to handle zero reads from the 821fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * device, since some devices can't do them at all due to shortcomings 822fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of the USB slave controller in the device. 823fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 824fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define CONTEXT_BLOCK_SIZE_1 0x3e00 825fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define CONTEXT_BLOCK_SIZE_2 0x200 826fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define CONTEXT_BLOCK_SIZE CONTEXT_BLOCK_SIZE_1+CONTEXT_BLOCK_SIZE_2 827fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic short 828fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_read_func ( 829fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long size, PTPDataHandler *handler,void *data, 830fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long *readbytes, 831fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int readzero 832fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 833fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)data; 834fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long toread = 0; 835fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret = 0; 836fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int xread; 837fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long curread = 0; 838fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long written; 839fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *bytes; 840fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int expect_terminator_byte = 0; 8414a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long usb_inep_maxpacket_size; 8424a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long context_block_size_1; 8434a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long context_block_size_2; 8444a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu uint16_t ptp_dev_vendor_id = ptp_usb->rawdevice.device_entry.vendor_id; 8454a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu 8464a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu //"iRiver" device special handling 8474a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu if (ptp_dev_vendor_id == 0x4102 || ptp_dev_vendor_id == 0x1006) { 8484a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu usb_inep_maxpacket_size = ptp_usb->inep_maxpacket; 8494a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu if (usb_inep_maxpacket_size == 0x400) { 8504a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_1 = CONTEXT_BLOCK_SIZE_1 - 0x200; 8514a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_2 = CONTEXT_BLOCK_SIZE_2 + 0x200; 8524a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 8534a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else { 8544a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_1 = CONTEXT_BLOCK_SIZE_1; 8554a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_2 = CONTEXT_BLOCK_SIZE_2; 8564a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 8574a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 858fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This is the largest block we'll need to read in. 859fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes = malloc(CONTEXT_BLOCK_SIZE); 860fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (curread < size) { 861fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 862fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Remaining size to read: 0x%04lx bytes\n", size - curread); 863fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 864fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // check equal to condition here 865fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (size - curread < CONTEXT_BLOCK_SIZE) 866fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 867fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // this is the last packet 868fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij toread = size - curread; 869fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // this is equivalent to zero read for these devices 870fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (readzero && FLAG_NO_ZERO_READS(ptp_usb) && toread % 64 == 0) { 871fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij toread += 1; 872fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij expect_terminator_byte = 1; 873fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 874fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 8754a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else if (ptp_dev_vendor_id == 0x4102 || ptp_dev_vendor_id == 0x1006) { 8764a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu //"iRiver" device special handling 8774a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu if (curread == 0) 8784a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu // we are first packet, but not last packet 8794a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = context_block_size_1; 8804a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else if (toread == context_block_size_1) 8814a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = context_block_size_2; 8824a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else if (toread == context_block_size_2) 8834a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = context_block_size_1; 8844a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else 8854a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu LIBMTP_INFO("unexpected toread size 0x%04x, 0x%04x remaining bytes\n", 8864a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu (unsigned int) toread, (unsigned int) (size-curread)); 8874a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 888fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 8894a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = CONTEXT_BLOCK_SIZE; 890fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 891fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Reading in 0x%04lx bytes\n", toread); 892fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 893fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = USB_BULK_READ(ptp_usb->handle, 894fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 895fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes, 896fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij toread, 897fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 898fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 899fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 900fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Result of read: 0x%04x (%d bytes)\n", ret, xread); 901fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 902fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) 903fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 904fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 905fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("<==USB IN\n"); 906fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xread == 0) 907fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Zero Read\n"); 908fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 909fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(bytes, xread, 16); 910fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 911fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // want to discard extra byte 912fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (expect_terminator_byte && xread == toread) 913fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 914fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("<==USB IN\nDiscarding extra byte\n"); 915fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 916fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij xread--; 917fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 918fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 919fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int putfunc_ret = handler->putfunc(NULL, handler->priv, xread, bytes, &written); 920fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (putfunc_ret != PTP_RC_OK) 921fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return putfunc_ret; 922fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 923fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete += xread; 924fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij curread += xread; 925fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 926fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Increase counters, call callback 927fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->callback_active) { 928fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_complete >= ptp_usb->current_transfer_total) { 929fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // send last update and disable callback. 930fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete = ptp_usb->current_transfer_total; 931fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->callback_active = 0; 932fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 933fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_callback != NULL) { 934fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 935fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb->current_transfer_callback(ptp_usb->current_transfer_complete, 936fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_total, 937fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_callback_data); 938fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != 0) { 939fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_CANCEL; 940fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 941fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 942fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 943fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 944fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xread < toread) /* short reads are common */ 945fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 946fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 947fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (readbytes) *readbytes = curread; 948fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (bytes); 949fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 950fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // there might be a zero packet waiting for us... 951fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (readzero && 952fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij !FLAG_NO_ZERO_READS(ptp_usb) && 953fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij curread % ptp_usb->outep_maxpacket == 0) { 954fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char temp; 955fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int zeroresult = 0, xread; 956fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 957fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("<==USB IN\n"); 958fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Zero Read\n"); 959fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 960fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij zeroresult = USB_BULK_READ(ptp_usb->handle, 961fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 962fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &temp, 963fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 964fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 965fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 966fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (zeroresult != LIBUSB_SUCCESS) 967fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("LIBMTP panic: unable to read in zero packet, response 0x%04x", zeroresult); 968fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 969fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 970fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 971fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 972fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 973fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic short 974fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_write_func ( 975fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long size, 976fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler *handler, 977fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij void *data, 978fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long *written 979fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 980fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)data; 981fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long towrite = 0; 982fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret = 0; 983fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long curwrite = 0; 984fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *bytes; 985fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 986fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This is the largest block we'll need to read in. 987fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes = malloc(CONTEXT_BLOCK_SIZE); 988fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!bytes) { 989fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 990fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 991fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (curwrite < size) { 992fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long usbwritten = 0; 993c4b6a194d19c31f9cfcf4c12dddf803037aa01b3Marcus Meissner int xwritten = 0; 994fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 995fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite = size-curwrite; 996fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (towrite > CONTEXT_BLOCK_SIZE) { 997fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite = CONTEXT_BLOCK_SIZE; 998fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 999fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This magic makes packets the same size that WMP send them. 1000fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (towrite > ptp_usb->outep_maxpacket && towrite % ptp_usb->outep_maxpacket != 0) { 1001fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite -= towrite % ptp_usb->outep_maxpacket; 1002fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1003fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1004fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int getfunc_ret = handler->getfunc(NULL, handler->priv,towrite,bytes,&towrite); 10051e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang if (getfunc_ret != PTP_RC_OK) { 10061e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang free(bytes); 1007fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return getfunc_ret; 10081e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang } 1009fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (usbwritten < towrite) { 1010fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = USB_BULK_WRITE(ptp_usb->handle, 1011fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->outep, 1012fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes+usbwritten, 1013fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite-usbwritten, 1014fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xwritten, 1015fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1016fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1017fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("USB OUT==>\n"); 1018fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1019fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 10201e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang free(bytes); 1021fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1022fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1023fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(bytes+usbwritten, xwritten, 16); 1024fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // check for result == 0 perhaps too. 1025fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Increase counters 1026fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete += xwritten; 1027fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij curwrite += xwritten; 1028fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbwritten += xwritten; 1029fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1030fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // call callback 1031fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->callback_active) { 1032fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_complete >= ptp_usb->current_transfer_total) { 1033fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // send last update and disable callback. 1034fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete = ptp_usb->current_transfer_total; 1035fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->callback_active = 0; 1036fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1037fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_callback != NULL) { 1038fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1039fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb->current_transfer_callback(ptp_usb->current_transfer_complete, 1040fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_total, 1041fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_callback_data); 1042fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != 0) { 10431e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang free(bytes); 1044fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_CANCEL; 1045fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1046fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1047fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1048fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xwritten < towrite) /* short writes happen */ 1049fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1050fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1051fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (bytes); 1052fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (written) { 1053fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *written = curwrite; 1054fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1055fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1056fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // If this is the last transfer send a zero write if required 1057fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_complete >= ptp_usb->current_transfer_total) { 1058fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((towrite % ptp_usb->outep_maxpacket) == 0) { 1059fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int xwritten; 1060fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1061fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("USB OUT==>\n"); 1062fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Zero Write\n"); 1063fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1064fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret =USB_BULK_WRITE(ptp_usb->handle, 1065fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->outep, 1066fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) "x", 1067fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 1068fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xwritten, 1069fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1070fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1071fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1072fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1073fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) 1074fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1075fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1076fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1077fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1078fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* memory data get/put handler */ 1079fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijtypedef struct { 1080fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *data; 1081fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long size, curoff; 1082fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} PTPMemHandlerPrivate; 1083fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1084fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1085fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijmemory_getfunc(PTPParams* params, void* private, 1086fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long wantlen, unsigned char *data, 1087fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long *gotlen 1088fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1089fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private; 1090fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long tocopy = wantlen; 1091fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1092fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (priv->curoff + tocopy > priv->size) 1093fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tocopy = priv->size - priv->curoff; 1094fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy (data, priv->data + priv->curoff, tocopy); 1095fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff += tocopy; 1096fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *gotlen = tocopy; 1097fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1098fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1099fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1100fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1101fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijmemory_putfunc(PTPParams* params, void* private, 1102fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long sendlen, unsigned char *data, 1103fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long *putlen 1104fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1105fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private; 1106fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1107fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (priv->curoff + sendlen > priv->size) { 1108fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->data = realloc (priv->data, priv->curoff+sendlen); 1109fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->size = priv->curoff + sendlen; 1110fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1111fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy (priv->data + priv->curoff, data, sendlen); 1112fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff += sendlen; 1113fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *putlen = sendlen; 1114fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1115fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1116fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1117fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* init private struct for receiving data. */ 1118fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1119fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_init_recv_memory_handler(PTPDataHandler *handler) { 1120fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv; 1121fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv = malloc (sizeof(PTPMemHandlerPrivate)); 1122fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->priv = priv; 1123fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->getfunc = memory_getfunc; 1124fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc = memory_putfunc; 1125fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->data = NULL; 1126fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->size = 0; 1127fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff = 0; 1128fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1129fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1130fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1131fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* init private struct and put data in for sending data. 1132fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * data is still owned by caller. 1133fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1134fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1135fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_init_send_memory_handler(PTPDataHandler *handler, 1136fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *data, unsigned long len 1137fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1138fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv; 1139fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv = malloc (sizeof(PTPMemHandlerPrivate)); 1140fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!priv) 1141fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_GeneralError; 1142fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->priv = priv; 1143fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->getfunc = memory_getfunc; 1144fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc = memory_putfunc; 1145fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->data = data; 1146fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->size = len; 1147fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff = 0; 1148fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1149fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1150fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1151fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* free private struct + data */ 1152fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1153fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_exit_send_memory_handler (PTPDataHandler *handler) { 1154fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv; 1155fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* data is owned by caller */ 1156fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (priv); 1157fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1158fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1159fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1160fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* hand over our internal data to caller */ 1161fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1162fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_exit_recv_memory_handler (PTPDataHandler *handler, 1163fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char **data, unsigned long *size 1164fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1165fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv; 1166fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *data = priv->data; 1167fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *size = priv->size; 1168fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (priv); 1169fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1170fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1171fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1172fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* send / receive functions */ 1173fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1174fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1175fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_sendreq (PTPParams* params, PTPContainer* req) 1176fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1177fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1178fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbreq; 1179fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler memhandler; 1180fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long written = 0; 1181fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long towrite; 1182fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1183fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij char txt[256]; 1184fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1185fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (void) ptp_render_opcode (params, req->Code, sizeof(txt), txt); 1186fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("REQUEST: 0x%04x, %s\n", req->Code, txt); 1187fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1188fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build appropriate USB container */ 1189fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.length=htod32(PTP_USB_BULK_REQ_LEN- 1190fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (sizeof(uint32_t)*(5-req->Nparam))); 1191fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.type=htod16(PTP_USB_CONTAINER_COMMAND); 1192fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.code=htod16(req->Code); 1193fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.trans_id=htod32(req->Transaction_ID); 1194fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param1=htod32(req->Param1); 1195fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param2=htod32(req->Param2); 1196fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param3=htod32(req->Param3); 1197fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param4=htod32(req->Param4); 1198fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param5=htod32(req->Param5); 1199fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* send it to responder */ 1200fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite = PTP_USB_BULK_REQ_LEN-(sizeof(uint32_t)*(5-req->Nparam)); 1201fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_init_send_memory_handler (&memhandler, (unsigned char*)&usbreq, towrite); 1202fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret=ptp_write_func( 1203fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite, 1204fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &memhandler, 1205fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data, 1206fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &written 1207fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1208fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_exit_send_memory_handler (&memhandler); 1209fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK && ret != PTP_ERROR_CANCEL) { 1210fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1211fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1212fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (written != towrite && ret != PTP_ERROR_CANCEL && ret != PTP_ERROR_IO) { 1213fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_error (params, 1214fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: request code 0x%04x sending req wrote only %ld bytes instead of %d", 1215fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij req->Code, written, towrite 1216fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1217fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1218fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1219fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1220fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1221fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1222fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1223fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_senddata (PTPParams* params, PTPContainer* ptp, 1224b3aaade14e14a67419c3edf6367b50599eec134fLinus Walleij uint64_t size, PTPDataHandler *handler 1225fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1226fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1227fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int wlen, datawlen; 1228fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long written; 1229fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbdata; 12301a5fe0ae4de66d1ca97f7ae712d75b409b1a7841Philip Langdale uint64_t bytes_left_to_transfer; 1231fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler memhandler; 1232fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1233fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1234fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("SEND DATA PHASE\n"); 1235fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1236fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build appropriate USB container */ 1237fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.length = htod32(PTP_USB_BULK_HDR_LEN+size); 1238fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.type = htod16(PTP_USB_CONTAINER_DATA); 1239fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.code = htod16(ptp->Code); 1240fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.trans_id= htod32(ptp->Transaction_ID); 1241fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1242fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ((PTP_USB*)params->data)->current_transfer_complete = 0; 1243fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ((PTP_USB*)params->data)->current_transfer_total = size+PTP_USB_BULK_HDR_LEN; 1244fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1245fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->split_header_data) { 1246fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij datawlen = 0; 1247fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij wlen = PTP_USB_BULK_HDR_LEN; 1248fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 1249fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long gotlen; 1250fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* For all camera devices. */ 1251fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij datawlen = (size<PTP_USB_BULK_PAYLOAD_LEN_WRITE)?size:PTP_USB_BULK_PAYLOAD_LEN_WRITE; 1252fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij wlen = PTP_USB_BULK_HDR_LEN + datawlen; 1253fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1254fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = handler->getfunc(params, handler->priv, datawlen, usbdata.payload.data, &gotlen); 1255fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != PTP_RC_OK) 1256fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1257fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (gotlen != datawlen) 1258fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_GeneralError; 1259fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1260fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_init_send_memory_handler (&memhandler, (unsigned char *)&usbdata, wlen); 1261fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* send first part of data */ 1262fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_write_func(wlen, &memhandler, params->data, &written); 1263fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_exit_send_memory_handler (&memhandler); 1264fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1265fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1266fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1267fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (size <= datawlen) return ret; 1268fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* if everything OK send the rest */ 1269fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_left_to_transfer = size-datawlen; 1270fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_RC_OK; 1271fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while(bytes_left_to_transfer > 0) { 12721165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner ret = ptp_write_func (bytes_left_to_transfer, handler, params->data, &written); 1273fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != PTP_RC_OK) 1274fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1275fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (written == 0) { 1276fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1277fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1278fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1279fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_left_to_transfer -= written; 1280fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1281fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK && ret != PTP_ERROR_CANCEL) 1282fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1283fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1284fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1285fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1286fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t ptp_usb_getpacket(PTPParams *params, 1287fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer *packet, unsigned long *rlen) 1288fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1289fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler memhandler; 1290fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1291fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *x = NULL; 12924a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long packet_size; 12934a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu PTP_USB *ptp_usb = (PTP_USB *) params->data; 12944a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu 12954a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu packet_size = ptp_usb->inep_maxpacket; 1296fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1297fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* read the header and potentially the first data */ 1298fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->response_packet_size > 0) { 1299fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If there is a buffered packet, just use it. */ 1300fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy(packet, params->response_packet, params->response_packet_size); 1301fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *rlen = params->response_packet_size; 1302fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free(params->response_packet); 1303fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet = NULL; 1304fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet_size = 0; 1305fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Here this signifies a "virtual read" */ 1306fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1307fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1308fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_init_recv_memory_handler (&memhandler); 13094a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu ret = ptp_read_func(packet_size, &memhandler, params->data, rlen, 0); 1310fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_exit_recv_memory_handler (&memhandler, &x, rlen); 1311fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (x) { 1312fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy (packet, x, *rlen); 1313fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (x); 1314fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1315fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1316fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1317fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1318fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1319fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) 1320fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1321fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1322fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbdata; 1323fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long written; 1324fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *) params->data; 1325fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int putfunc_ret; 1326fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1327fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("GET DATA PHASE\n"); 1328fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1329fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(&usbdata,0,sizeof(usbdata)); 1330fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij do { 1331fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long len, rlen; 1332fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1333fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb_getpacket(params, &usbdata, &rlen); 1334fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1335fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1336fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1337fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1338fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbdata.type)!=PTP_USB_CONTAINER_DATA) { 1339fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_DATA_EXPECTED; 1340fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1341fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1342fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbdata.code)!=ptp->Code) { 1343fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_IGNORE_HEADER_ERRORS(ptp_usb)) { 1344fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp2/ptp_usb_getdata: detected a broken " 1345fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP header, code field insane, expect problems! (But continuing)"); 1346fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Repair the header, so it won't wreak more havoc, don't just ignore it. 1347fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Typically these two fields will be broken. 1348fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.code = htod16(ptp->Code); 1349fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.trans_id = htod32(ptp->Transaction_ID); 1350fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_RC_OK; 1351fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 1352fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = dtoh16(usbdata.code); 1353fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This filters entirely insane garbage return codes, but still 1354fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // makes it possible to return error codes in the code field when 1355fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // getting data. It appears Windows ignores the contents of this 1356fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // field entirely. 1357fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < PTP_RC_Undefined || ret > PTP_RC_SpecificationOfDestinationUnsupported) { 1358fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp2/ptp_usb_getdata: detected a broken " 1359fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP header, code field insane."); 1360fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1361fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1362fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1363fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1364fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1365aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner if (rlen == ptp_usb->inep_maxpacket) { 1366fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy first part of data to 'data' */ 1367fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij putfunc_ret = 1368fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc( 1369fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, usbdata.payload.data, 1370fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &written 1371fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1372fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (putfunc_ret != PTP_RC_OK) 1373fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return putfunc_ret; 1374fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1375fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* stuff data directly to passed data handler */ 1376fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (1) { 1377fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long readdata; 1378fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t xret; 1379fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 13801165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner xret = ptp_read_func( 1381e6f7703dd1749504ed9060e1bc55f82ecc456af6Philip Langdale 0x20000000, 1382fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler, 1383fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data, 1384fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &readdata, 1385fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0 1386fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1387fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xret != PTP_RC_OK) 1388fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return xret; 1389e6f7703dd1749504ed9060e1bc55f82ecc456af6Philip Langdale if (readdata < 0x20000000) 1390fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1391fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1392fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1393fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1394fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (rlen > dtoh32(usbdata.length)) { 1395fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1396fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Buffer the surplus response packet if it is >= 1397fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * PTP_USB_BULK_HDR_LEN 1398fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * (i.e. it is probably an entire package) 1399fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * else discard it as erroneous surplus data. 1400fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This will even work if more than 2 packets appear 1401fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * in the same transaction, they will just be handled 1402fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * iteratively. 1403fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 1404fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Marcus observed stray bytes on iRiver devices; 1405fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * these are still discarded. 1406fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1407fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned int packlen = dtoh32(usbdata.length); 1408fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned int surplen = rlen - packlen; 1409fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1410fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (surplen >= PTP_USB_BULK_HDR_LEN) { 1411fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet = malloc(surplen); 1412fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy(params->response_packet, 1413fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (uint8_t *) &usbdata + packlen, surplen); 1414fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet_size = surplen; 1415fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Ignore reading one extra byte if device flags have been set */ 1416fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if(!FLAG_NO_ZERO_READS(ptp_usb) && 1417fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (rlen - dtoh32(usbdata.length) == 1)) { 1418fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp2/ptp_usb_getdata: read %d bytes " 1419fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "too much, expect problems!", 1420fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij rlen - dtoh32(usbdata.length)); 1421fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1422fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij rlen = packlen; 1423fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1424fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1425fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* For most PTP devices rlen is 512 == sizeof(usbdata) 1426fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * here. For MTP devices splitting header and data it might 1427fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * be 12. 1428fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1429fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Evaluate full data length. */ 1430fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij len=dtoh32(usbdata.length)-PTP_USB_BULK_HDR_LEN; 1431fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1432fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* autodetect split header/data MTP devices */ 1433fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh32(usbdata.length) > 12 && (rlen==12)) 1434fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->split_header_data = 1; 1435fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1436fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy first part of data to 'data' */ 1437fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij putfunc_ret = 1438fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc( 1439fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, 1440fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.payload.data, 1441fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &written 1442fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1443fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (putfunc_ret != PTP_RC_OK) 1444fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return putfunc_ret; 1445fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1446fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_NO_ZERO_READS(ptp_usb) && 1447aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner len+PTP_USB_BULK_HDR_LEN == ptp_usb->inep_maxpacket) { 1448fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1449fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Reading in extra terminating byte\n"); 1450fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1451fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // need to read in extra byte and discard it 1452fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int result = 0, xread; 1453fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char byte = 0; 1454fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1455fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 1456fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &byte, 1457fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1, 1458fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1459fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1460fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1461fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (result != 1) 1462aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner LIBMTP_INFO("Could not read in extra byte for %d byte long file, return value 0x%04x\n", ptp_usb->inep_maxpacket, result); 1463aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner } else if (len+PTP_USB_BULK_HDR_LEN == ptp_usb->inep_maxpacket && params->split_header_data == 0) { 1464fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int zeroresult = 0, xread; 1465fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char zerobyte = 0; 1466fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1467fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("Reading in zero packet after header\n"); 1468fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1469fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij zeroresult = USB_BULK_READ(ptp_usb->handle, 1470fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 1471fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &zerobyte, 1472fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 1473fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1474fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1475fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1476fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (zeroresult != 0) 1477fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("LIBMTP panic: unable to read in zero packet, response 0x%04x", zeroresult); 1478fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1479fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1480fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Is that all of data? */ 1481fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (len+PTP_USB_BULK_HDR_LEN<=rlen) { 1482fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1483fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1484fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 14851165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner ret = ptp_read_func(len - (rlen - PTP_USB_BULK_HDR_LEN), 1486fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler, 1487fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data, &rlen, 1); 1488fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1489fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1490fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1491fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1492fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } while (0); 1493fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1494fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1495fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1496fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1497fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_getresp (PTPParams* params, PTPContainer* resp) 1498fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1499fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1500fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long rlen; 1501fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbresp; 1502fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)(params->data); 1503fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1504fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1505fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("RESPONSE: "); 1506fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1507fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(&usbresp,0,sizeof(usbresp)); 1508fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* read response, it should never be longer than sizeof(usbresp) */ 1509fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb_getpacket(params, &usbresp, &rlen); 1510fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1511fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Fix for bevahiour reported by Scott Snyder on Samsung YP-U3. The player 1512fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // sends a packet containing just zeroes of length 2 (up to 4 has been seen too) 1513fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // after a NULL packet when it should send the response. This code ignores 1514fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // such illegal packets. 1515fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (ret==PTP_RC_OK && rlen<PTP_USB_BULK_HDR_LEN && usbresp.length==0) { 1516fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp_usb_getresp: detected short response " 1517fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "of %d bytes, expect problems! (re-reading " 1518fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "response), rlen"); 1519fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb_getpacket(params, &usbresp, &rlen); 1520fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1521fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1522fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1523fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1524fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else 1525fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbresp.type)!=PTP_USB_CONTAINER_RESPONSE) { 1526fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_RESP_EXPECTED; 1527fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else 1528fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbresp.code)!=resp->Code) { 1529fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = dtoh16(usbresp.code); 1530fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1531fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1532fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("%04x\n", ret); 1533fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1534fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1535fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* libusb_glue_error (params, 1536fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: request code 0x%04x getting resp error 0x%04x", 1537fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Code, ret);*/ 1538fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1539fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1540fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build an appropriate PTPContainer */ 1541fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Code=dtoh16(usbresp.code); 1542fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->SessionID=params->session_id; 1543fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Transaction_ID=dtoh32(usbresp.trans_id); 1544fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_IGNORE_HEADER_ERRORS(ptp_usb)) { 1545fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (resp->Transaction_ID != params->transaction_id-1) { 1546fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp_usb_getresp: detected a broken " 1547fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP header, transaction ID insane, expect " 1548fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "problems! (But continuing)"); 1549fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Repair the header, so it won't wreak more havoc. 1550fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Transaction_ID = params->transaction_id-1; 1551fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1552fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1553fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param1=dtoh32(usbresp.payload.params.param1); 1554fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param2=dtoh32(usbresp.payload.params.param2); 1555fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param3=dtoh32(usbresp.payload.params.param3); 1556fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param4=dtoh32(usbresp.payload.params.param4); 1557fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param5=dtoh32(usbresp.payload.params.param5); 1558fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1559fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1560fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1561fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* Event handling functions */ 1562fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1563fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* PTP Events wait for or check mode */ 1564fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define PTP_EVENT_CHECK 0x0000 /* waits for */ 1565fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define PTP_EVENT_CHECK_FAST 0x0001 /* checks */ 1566fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1567fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic inline uint16_t 1568fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_event (PTPParams* params, PTPContainer* event, int wait) 1569fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1570fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1571fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int result, xread; 1572fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long rlen; 1573fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBEventContainer usbevent; 157450ed219a5d4dc4bce71a0a0ebd59e8d9f9a98f9eMarcus Meissner PTP_USB *ptp_usb; 1575fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1576fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(&usbevent,0,sizeof(usbevent)); 1577fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1578fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((params==NULL) || (event==NULL)) 1579fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_BADPARAM; 158050ed219a5d4dc4bce71a0a0ebd59e8d9f9a98f9eMarcus Meissner ptp_usb = (PTP_USB *)(params->data); 158150ed219a5d4dc4bce71a0a0ebd59e8d9f9a98f9eMarcus Meissner 1582fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_RC_OK; 1583fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij switch(wait) { 1584fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case PTP_EVENT_CHECK: 15857433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1586fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1587fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1588fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1589fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1590fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0); 15917433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij if (xread == 0) 1592fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1593fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1594fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1595fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1596fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1597fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0); 1598fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (result < 0) ret = PTP_ERROR_IO; 1599fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1600fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case PTP_EVENT_CHECK_FAST: 16017433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1602fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1603fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1604fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1605fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1606fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 16077433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij if (xread == 0) 1608fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1609fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1610fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1611fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1612fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1613fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1614fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (result < 0) ret = PTP_ERROR_IO; 1615fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1616fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij default: 16177433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij ret = PTP_ERROR_BADPARAM; 1618fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1619fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1620fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1621fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_error (params, 1622fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: reading event an error 0x%04x occurred", ret); 1623fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1624fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 16257433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij rlen = xread; 1626fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (rlen < 8) { 1627fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_error (params, 1628fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: reading event an short read of %ld bytes occurred", rlen); 1629fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1630fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1631fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* if we read anything over interrupt endpoint it must be an event */ 1632fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build an appropriate PTPContainer */ 1633fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Code=dtoh16(usbevent.code); 1634fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->SessionID=params->session_id; 1635fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Transaction_ID=dtoh32(usbevent.trans_id); 1636fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Param1=dtoh32(usbevent.param1); 1637fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Param2=dtoh32(usbevent.param2); 1638fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Param3=dtoh32(usbevent.param3); 1639fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1640fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1641fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1642fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1643fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_event_check (PTPParams* params, PTPContainer* event) { 1644fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1645fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ptp_usb_event (params, event, PTP_EVENT_CHECK_FAST); 1646fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1647fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1648fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1649fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_event_wait (PTPParams* params, PTPContainer* event) { 1650fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1651fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ptp_usb_event (params, event, PTP_EVENT_CHECK); 1652fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1653fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1654fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1655fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_control_cancel_request (PTPParams *params, uint32_t transactionid) { 1656fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)(params->data); 1657fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1658fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char buffer[6]; 1659fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1660fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij htod16a(&buffer[0],PTP_EC_CancelTransaction); 1661fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij htod32a(&buffer[2],transactionid); 1662fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(ptp_usb->handle, 1663fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, 1664fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0x64, 0x0000, 0x0000, 1665fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buffer, 1666fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(buffer), 1667fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1668fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < sizeof(buffer)) 1669fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1670fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1671fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1672fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 167315d18e31458be5006eb229df68869df2fff93495Linus Walleijstatic int init_ptp_usb(PTPParams* params, PTP_USB* ptp_usb, libusb_device* dev) 1674fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1675fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device_handle *device_handle; 1676fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char buf[255]; 1677fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret, usbresult; 167815d18e31458be5006eb229df68869df2fff93495Linus Walleij struct libusb_config_descriptor *config; 1679fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1680fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->sendreq_func=ptp_usb_sendreq; 1681fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->senddata_func=ptp_usb_senddata; 1682fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->getresp_func=ptp_usb_getresp; 1683fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->getdata_func=ptp_usb_getdata; 1684fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->cancelreq_func=ptp_usb_control_cancel_request; 1685fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data=ptp_usb; 1686fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->transaction_id=0; 1687fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1688fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This is hardcoded here since we have no devices whatsoever that are BE. 1689fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Change this the day we run into our first BE device (if ever). 1690fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1691fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->byteorder = PTP_DL_LE; 1692fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1693fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout = get_timeout(ptp_usb); 1694fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1695fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_open(dev, &device_handle); 1696fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 169715d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_open() failed!"); 1698fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return -1; 1699fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1700fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->handle = device_handle; 170115d18e31458be5006eb229df68869df2fff93495Linus Walleij 1702fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1703fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * If this device is known to be wrongfully claimed by other kernel 1704fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * drivers (such as mass storage), then try to unload it to make it 1705fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * accessible from user space. 1706fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1707fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_UNLOAD_DRIVER(ptp_usb) && 170815d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_kernel_driver_active(device_handle, ptp_usb->interface) 1709fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ) { 171015d18e31458be5006eb229df68869df2fff93495Linus Walleij if (LIBUSB_SUCCESS != libusb_detach_kernel_driver(device_handle, ptp_usb->interface)) { 171115d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_detach_kernel_driver() failed, continuing anyway..."); 1712fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1713fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 171415d18e31458be5006eb229df68869df2fff93495Linus Walleij 171515d18e31458be5006eb229df68869df2fff93495Linus Walleij /* 171615d18e31458be5006eb229df68869df2fff93495Linus Walleij * Check if the config is set to something else than what we want 171715d18e31458be5006eb229df68869df2fff93495Linus Walleij * to use. Only set the configuration if we absolutely have to. 171815d18e31458be5006eb229df68869df2fff93495Linus Walleij * Also do not bail out if we fail. 1719d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij * 1720d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij * Note that Darwin will not set the configuration for vendor-specific 1721d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij * devices so we need to go in and set it. 172215d18e31458be5006eb229df68869df2fff93495Linus Walleij */ 172315d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_active_config_descriptor(dev, &config); 172415d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ret != LIBUSB_SUCCESS) { 172515d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_get_active_config_descriptor(1) failed"); 1726d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij fprintf(stderr, "no active configuration, trying to set configuration\n"); 1727d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij if (libusb_set_configuration(device_handle, ptp_usb->config) != LIBUSB_SUCCESS) { 1728d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij perror("libusb_set_configuration() failed, continuing anyway..."); 1729d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij } 1730d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij ret = libusb_get_active_config_descriptor(dev, &config); 1731d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij if (ret != LIBUSB_SUCCESS) { 1732d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij perror("libusb_get_active_config_descriptor(2) failed"); 1733d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij return -1; 1734d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij } 1735fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 173615d18e31458be5006eb229df68869df2fff93495Linus Walleij if (config->bConfigurationValue != ptp_usb->config) { 173715d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "desired configuration different from current, trying to set configuration\n"); 173815d18e31458be5006eb229df68869df2fff93495Linus Walleij if (libusb_set_configuration(device_handle, ptp_usb->config)) { 173915d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_set_configuration() failed, continuing anyway..."); 174015d18e31458be5006eb229df68869df2fff93495Linus Walleij } 174115d18e31458be5006eb229df68869df2fff93495Linus Walleij /* Re-fetch the config descriptor if we changed */ 174215d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 174315d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_active_config_descriptor(dev, &config); 174415d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ret != LIBUSB_SUCCESS) { 174515d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_get_active_config_descriptor(2) failed"); 174615d18e31458be5006eb229df68869df2fff93495Linus Walleij return -1; 174715d18e31458be5006eb229df68869df2fff93495Linus Walleij } 174815d18e31458be5006eb229df68869df2fff93495Linus Walleij } 174915d18e31458be5006eb229df68869df2fff93495Linus Walleij 175015d18e31458be5006eb229df68869df2fff93495Linus Walleij /* 175115d18e31458be5006eb229df68869df2fff93495Linus Walleij * It seems like on kernel 2.6.31 if we already have it open on another 175215d18e31458be5006eb229df68869df2fff93495Linus Walleij * pthread in our app, we'll get an error if we try to claim it again, 175315d18e31458be5006eb229df68869df2fff93495Linus Walleij * but that error is harmless because our process already claimed the interface 175415d18e31458be5006eb229df68869df2fff93495Linus Walleij */ 1755fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbresult = libusb_claim_interface(device_handle, ptp_usb->interface); 1756fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1757fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (usbresult != 0) 175815d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "ignoring libusb_claim_interface() = %d", usbresult); 175915d18e31458be5006eb229df68869df2fff93495Linus Walleij 176015d18e31458be5006eb229df68869df2fff93495Linus Walleij /* 176115d18e31458be5006eb229df68869df2fff93495Linus Walleij * If the altsetting is set to something different than we want, switch 176215d18e31458be5006eb229df68869df2fff93495Linus Walleij * it. 176315d18e31458be5006eb229df68869df2fff93495Linus Walleij * 176415d18e31458be5006eb229df68869df2fff93495Linus Walleij * FIXME: this seems to cause trouble on the Mac:s so disable it. Retry 176515d18e31458be5006eb229df68869df2fff93495Linus Walleij * this on the Mac now that it only sets this when the altsetting differs. 176615d18e31458be5006eb229df68869df2fff93495Linus Walleij */ 1767fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#ifndef __APPLE__ 176815d18e31458be5006eb229df68869df2fff93495Linus Walleij#if 0 /* Disable this always, no idea on how to handle it */ 176915d18e31458be5006eb229df68869df2fff93495Linus Walleij if (config->interface[].altsetting[].bAlternateSetting != 177015d18e31458be5006eb229df68869df2fff93495Linus Walleij ptp_usb->altsetting) { 177115d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "desired altsetting different from current, trying to set altsetting\n"); 177215d18e31458be5006eb229df68869df2fff93495Linus Walleij usbresult = libusb_set_interface_alt_setting(device_handle, 177315d18e31458be5006eb229df68869df2fff93495Linus Walleij ptp_usb->interface, 177415d18e31458be5006eb229df68869df2fff93495Linus Walleij ptp_usb->altsetting); 177515d18e31458be5006eb229df68869df2fff93495Linus Walleij if (usbresult != 0) 177615d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "ignoring libusb_set_interface_alt_setting() = %d\n", usbresult); 177715d18e31458be5006eb229df68869df2fff93495Linus Walleij } 177815d18e31458be5006eb229df68869df2fff93495Linus Walleij#endif 1779fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#endif 1780fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 178115d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 178215d18e31458be5006eb229df68869df2fff93495Linus Walleij 1783fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_SWITCH_MODE_BLACKBERRY(ptp_usb)) { 1784fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1785fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1786fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // FIXME : Only for BlackBerry Storm 1787fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // What does it mean? Maybe switch mode... 1788fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This first control message is absolutely necessary 1789fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1790fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1791fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1792fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xaa, 0x00, 0x04, buf, 0x40, 1000); 1793fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 1:\n"); 1794fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1795fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1796fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1797fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This control message is unnecessary 1798fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1799fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1800fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xa5, 0x00, 0x01, buf, 0x02, 1000); 1801fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 2:\n"); 1802fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1803fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1804fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1805fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This control message is unnecessary 1806fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1807fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1808fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xa8, 0x00, 0x01, buf, 0x05, 1000); 1809fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 3:\n"); 1810fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1811fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1812fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1813fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This control message is unnecessary 1814fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1815fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1816fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xa8, 0x00, 0x01, buf, 0x11, 1000); 1817fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 4:\n"); 1818fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1819fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1820fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1821fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1822fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 1823fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1824fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1825fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void clear_stall(PTP_USB* ptp_usb) 1826fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1827fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t status; 1828fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1829fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1830fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* check the inep status */ 1831fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij status = 0; 1832fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = usb_get_endpoint_status(ptp_usb,ptp_usb->inep,&status); 1833fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret<0) { 1834fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror ("inep: usb_get_endpoint_status()"); 1835fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (status) { 1836fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("Clearing stall on IN endpoint\n"); 1837fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_clear_halt (ptp_usb->handle, ptp_usb->inep); 1838fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 1839fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror ("usb_clear_stall_feature()"); 1840fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1841fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1842fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1843fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* check the outep status */ 1844fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij status=0; 1845fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = usb_get_endpoint_status(ptp_usb,ptp_usb->outep,&status); 1846fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret<0) { 1847fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror("outep: usb_get_endpoint_status()"); 1848fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (status) { 1849fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("Clearing stall on OUT endpoint\n"); 18501bc3a75fa2223884900136201d74905a0ad01426Linus Walleij ret = libusb_clear_halt(ptp_usb->handle, ptp_usb->outep); 1851fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 1852fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror("usb_clear_stall_feature()"); 1853fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1854fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1855fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1856fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* TODO: do we need this for INTERRUPT (ptp_usb->intep) too? */ 1857fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1858fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1859fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void close_usb(PTP_USB* ptp_usb) 1860fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1861fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!FLAG_NO_RELEASE_INTERFACE(ptp_usb)) { 1862fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1863fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Clear any stalled endpoints 1864fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * On misbehaving devices designed for Windows/Mac, quote from: 1865fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://www2.one-eyed-alien.net/~mdharm/linux-usb/target_offenses.txt 1866fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Device does Bad Things(tm) when it gets a GET_STATUS after CLEAR_HALT 1867fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * (...) Windows, when clearing a stall, only sends the CLEAR_HALT command, 1868fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * and presumes that the stall has cleared. Some devices actually choke 1869fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * if the CLEAR_HALT is followed by a GET_STATUS (used to determine if the 1870fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * STALL is persistant or not). 1871fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1872fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij clear_stall(ptp_usb); 1873fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_release_interface(ptp_usb->handle, (int) ptp_usb->interface); 1874fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1875fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_FORCE_RESET_ON_CLOSE(ptp_usb)) { 1876fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1877fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Some devices really love to get reset after being 1878fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * disconnected. Again, since Windows never disconnects 1879fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * a device closing behaviour is seldom or never exercised 1880fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * on devices when engineered and often error prone. 1881fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Reset may help some. 1882fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1883fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_reset_device (ptp_usb->handle); 1884fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1885fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(ptp_usb->handle); 1886fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1887fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1888fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 1889fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Self-explanatory? 1890fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1891fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int find_interface_and_endpoints(libusb_device *dev, 189215d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *conf, 1893fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t *interface, 189415d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *altsetting, 1895fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep, 1896fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep_maxpacket, 1897fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* outep, 1898fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int *outep_maxpacket, 1899fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* intep) 1900fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 190115d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t i, ret; 1902fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 1903fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 190415d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_device_descriptor(dev, &desc); 190515d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ret != LIBUSB_SUCCESS) 190615d18e31458be5006eb229df68869df2fff93495Linus Walleij return -1; 1907fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1908fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Loop over the device configurations 1909fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < desc.bNumConfigurations; i++) { 1910fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t j; 1911fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_config_descriptor *config; 1912fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 191315d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_config_descriptor(dev, i, &config); 191413bbf6aecb8ad3c2b0bb03dbb3500e8fe87cc08eMarcus Meissner if (ret != LIBUSB_SUCCESS) 191515d18e31458be5006eb229df68869df2fff93495Linus Walleij continue; 191615d18e31458be5006eb229df68869df2fff93495Linus Walleij 191715d18e31458be5006eb229df68869df2fff93495Linus Walleij *conf = config->bConfigurationValue; 191815d18e31458be5006eb229df68869df2fff93495Linus Walleij 1919fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Loop over each configurations interfaces 1920fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (j = 0; j < config->bNumInterfaces; j++) { 192115d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t k, l; 1922fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t no_ep; 1923fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_inep = 0; 1924fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_outep = 0; 1925fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_intep = 0; 1926fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij const struct libusb_endpoint_descriptor *ep; 1927fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 192815d18e31458be5006eb229df68869df2fff93495Linus Walleij // Inspect the altsettings of this interface... 192915d18e31458be5006eb229df68869df2fff93495Linus Walleij for (k = 0; k < config->interface[j].num_altsetting; k++) { 193015d18e31458be5006eb229df68869df2fff93495Linus Walleij 193115d18e31458be5006eb229df68869df2fff93495Linus Walleij // MTP devices shall have 3 endpoints, ignore those interfaces 193215d18e31458be5006eb229df68869df2fff93495Linus Walleij // that haven't. 193315d18e31458be5006eb229df68869df2fff93495Linus Walleij no_ep = config->interface[j].altsetting[k].bNumEndpoints; 193415d18e31458be5006eb229df68869df2fff93495Linus Walleij if (no_ep != 3) 193515d18e31458be5006eb229df68869df2fff93495Linus Walleij continue; 193615d18e31458be5006eb229df68869df2fff93495Linus Walleij 193715d18e31458be5006eb229df68869df2fff93495Linus Walleij *interface = config->interface[j].altsetting[k].bInterfaceNumber; 193815d18e31458be5006eb229df68869df2fff93495Linus Walleij *altsetting = config->interface[j].altsetting[k].bAlternateSetting; 193915d18e31458be5006eb229df68869df2fff93495Linus Walleij ep = config->interface[j].altsetting[k].endpoint; 194015d18e31458be5006eb229df68869df2fff93495Linus Walleij 194115d18e31458be5006eb229df68869df2fff93495Linus Walleij // Loop over the three endpoints to locate two bulk and 194215d18e31458be5006eb229df68869df2fff93495Linus Walleij // one interrupt endpoint and FAIL if we cannot, and continue. 194315d18e31458be5006eb229df68869df2fff93495Linus Walleij for (l = 0; l < no_ep; l++) { 194415d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_BULK) { 194515d18e31458be5006eb229df68869df2fff93495Linus Walleij if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 194615d18e31458be5006eb229df68869df2fff93495Linus Walleij LIBUSB_ENDPOINT_DIR_MASK) { 194715d18e31458be5006eb229df68869df2fff93495Linus Walleij *inep = ep[l].bEndpointAddress; 194815d18e31458be5006eb229df68869df2fff93495Linus Walleij *inep_maxpacket = ep[l].wMaxPacketSize; 194915d18e31458be5006eb229df68869df2fff93495Linus Walleij found_inep = 1; 195015d18e31458be5006eb229df68869df2fff93495Linus Walleij } 195115d18e31458be5006eb229df68869df2fff93495Linus Walleij if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 0) { 195215d18e31458be5006eb229df68869df2fff93495Linus Walleij *outep = ep[l].bEndpointAddress; 195315d18e31458be5006eb229df68869df2fff93495Linus Walleij *outep_maxpacket = ep[l].wMaxPacketSize; 195415d18e31458be5006eb229df68869df2fff93495Linus Walleij found_outep = 1; 195515d18e31458be5006eb229df68869df2fff93495Linus Walleij } 195615d18e31458be5006eb229df68869df2fff93495Linus Walleij } else if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT) { 195715d18e31458be5006eb229df68869df2fff93495Linus Walleij if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 195815d18e31458be5006eb229df68869df2fff93495Linus Walleij LIBUSB_ENDPOINT_DIR_MASK) { 195915d18e31458be5006eb229df68869df2fff93495Linus Walleij *intep = ep[l].bEndpointAddress; 196015d18e31458be5006eb229df68869df2fff93495Linus Walleij found_intep = 1; 196115d18e31458be5006eb229df68869df2fff93495Linus Walleij } 1962fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1963fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 196415d18e31458be5006eb229df68869df2fff93495Linus Walleij if (found_inep && found_outep && found_intep) { 196515d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 196615d18e31458be5006eb229df68869df2fff93495Linus Walleij // We assigned the endpoints so return here. 196715d18e31458be5006eb229df68869df2fff93495Linus Walleij return 0; 196815d18e31458be5006eb229df68869df2fff93495Linus Walleij } 196915d18e31458be5006eb229df68869df2fff93495Linus Walleij } // Next altsetting 197015d18e31458be5006eb229df68869df2fff93495Linus Walleij } // Next interface 197115d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 197215d18e31458be5006eb229df68869df2fff93495Linus Walleij } // Next config 1973fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return -1; 1974fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1975fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1976fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 1977fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This function assigns params and usbinfo given a raw device 1978fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * as input. 1979fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param device the device to be assigned. 1980fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param usbinfo a pointer to the new usbinfo. 1981fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return an error code. 1982fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1983fbbef8b16876568f760986e4ff8f4921b8373fd5Linus WalleijLIBMTP_error_number_t configure_usb_device(LIBMTP_raw_device_t *device, 1984fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPParams *params, 1985fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij void **usbinfo) 1986fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1987fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb; 1988fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *ldevice; 1989fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret = 0; 1990fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int err, found = 0, i; 1991fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ssize_t nrofdevs; 1992fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device **devs = NULL; 1993fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 19943df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_error_number_t init_usb_ret; 1995fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1996fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* See if we can find this raw device again... */ 19973df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang init_usb_ret = init_usb(); 19983df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (init_usb_ret != LIBMTP_ERROR_NONE) 19993df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return init_usb_ret; 2000fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 200115d18e31458be5006eb229df68869df2fff93495Linus Walleij nrofdevs = libusb_get_device_list(NULL, &devs); 2002fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < nrofdevs ; i++) { 200315d18e31458be5006eb229df68869df2fff93495Linus Walleij if (libusb_get_bus_number(devs[i]) != device->bus_location) 2004fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 200515d18e31458be5006eb229df68869df2fff93495Linus Walleij if (libusb_get_device_address(devs[i]) != device->devnum) 2006fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 2007fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 200815d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_device_descriptor(devs[i], &desc); 2009fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) continue; 2010fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2011fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(desc.idVendor == device->device_entry.vendor_id && 2012fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct == device->device_entry.product_id ) { 2013fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ldevice = devs[i]; 2014fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found = 1; 2015fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2016fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2017fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2018fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Device has gone since detecting raw devices! */ 2019fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!found) { 2020fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_free_device_list (devs, 0); 2021fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NO_DEVICE_ATTACHED; 2022fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2023fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2024fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Allocate structs */ 2025fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb = (PTP_USB *) malloc(sizeof(PTP_USB)); 2026fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb == NULL) { 2027fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_free_device_list (devs, 0); 2028fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_MEMORY_ALLOCATION; 2029fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2030fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Start with a blank slate (includes setting device_flags to 0) */ 2031fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(ptp_usb, 0, sizeof(PTP_USB)); 2032fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2033fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy the raw device */ 2034fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy(&ptp_usb->rawdevice, device, sizeof(LIBMTP_raw_device_t)); 2035fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2036fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 2037fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Some devices must have their "OS Descriptor" massaged in order 2038fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to work. 2039fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 2040fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_ALWAYS_PROBE_DESCRIPTOR(ptp_usb)) { 2041fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Massage the device descriptor 2042fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (void) probe_device_descriptor(ldevice, NULL); 2043fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2044fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2045fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Assign interface and endpoints to usbinfo... */ 2046fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij err = find_interface_and_endpoints(ldevice, 204715d18e31458be5006eb229df68869df2fff93495Linus Walleij &ptp_usb->config, 2048fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->interface, 204915d18e31458be5006eb229df68869df2fff93495Linus Walleij &ptp_usb->altsetting, 2050fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->inep, 2051fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->inep_maxpacket, 2052fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->outep, 2053fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->outep_maxpacket, 2054fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->intep); 2055fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2056fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (err) { 2057fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_free_device_list (devs, 0); 2058fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2059fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Unable to find interface & endpoints of device\n"); 2060fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2061fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2062fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2063fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy USB version number */ 2064fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->bcdusb = desc.bcdUSB; 2065fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2066fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Attempt to initialize this device */ 2067fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (init_ptp_usb(params, ptp_usb, ldevice) < 0) { 2068fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2069fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Unable to initialize device\n"); 20701e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2071fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2072fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2073fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2074fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 2075fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This works in situations where previous bad applications 2076fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * have not used LIBMTP_Release_Device on exit 2077fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 2078fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((ret = ptp_opensession(params, 1)) == PTP_ERROR_IO) { 2079fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("PTP_ERROR_IO: failed to open session, trying again after resetting USB interface\n"); 2080fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP libusb: Attempt to reset device\n"); 2081fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_reset_device (ptp_usb->handle); 2082fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij close_usb(ptp_usb); 2083fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2084fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(init_ptp_usb(params, ptp_usb, ldevice) <0) { 2085fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Could not init USB on second attempt\n"); 20861e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2087fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2088fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2089fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2090fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2091fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Device has been reset, try again */ 2092fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((ret = ptp_opensession(params, 1)) == PTP_ERROR_IO) { 2093fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: failed to open session on second attempt\n"); 20941e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2095fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2096fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2097fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2098fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2099fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2100fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Was the transaction id invalid? Try again */ 2101fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret == PTP_RC_InvalidTransactionID) { 2102fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP WARNING: Transaction ID was invalid, increment and try again\n"); 2103fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->transaction_id += 10; 2104fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_opensession(params, 1); 2105fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2106fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2107fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != PTP_RC_SessionAlreadyOpened && ret != PTP_RC_OK) { 2108fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Could not open session! " 2109fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "(Return code %d)\n Try to reset the device.\n", 2110fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret); 2111fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_release_interface(ptp_usb->handle, ptp_usb->interface); 21121e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2113fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2114fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2115fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2116fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2117fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* OK configured properly */ 2118fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *usbinfo = (void *) ptp_usb; 21191e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2120fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 2121fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2122fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2123fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2124fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid close_device (PTP_USB *ptp_usb, PTPParams *params) 2125fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2126fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_closesession(params)!=PTP_RC_OK) 2127fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("ERROR: Could not close session!\n"); 2128fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij close_usb(ptp_usb); 2129fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2130fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2131fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid set_usb_device_timeout(PTP_USB *ptp_usb, int timeout) 2132fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2133fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout = timeout; 2134fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2135fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2136fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid get_usb_device_timeout(PTP_USB *ptp_usb, int *timeout) 2137fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2138fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *timeout = ptp_usb->timeout; 2139fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2140fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2141fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijint guess_usb_speed(PTP_USB *ptp_usb) 2142fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2143fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int bytes_per_second; 2144fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2145fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 2146fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We don't know the actual speeds so these are rough guesses 2147fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * from the info you can find here: 2148fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://en.wikipedia.org/wiki/USB#Transfer_rates 2149fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://www.barefeats.com/usb2.html 2150fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 2151fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij switch (ptp_usb->bcdusb & 0xFF00) { 2152fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case 0x0100: 2153fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1.x USB versions let's say 1MiB/s */ 2154fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_per_second = 1*1024*1024; 2155fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2156fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case 0x0200: 2157fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case 0x0300: 2158fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* USB 2.0 nominal speed 18MiB/s */ 2159fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* USB 3.0 won't be worse? */ 2160fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_per_second = 18*1024*1024; 2161fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2162fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij default: 2163fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Half-guess something? */ 2164fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_per_second = 1*1024*1024; 2165fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2166fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2167fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return bytes_per_second; 2168fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2169fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2170fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status) 2171fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2172fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return libusb_control_transfer(ptp_usb->handle, 2173fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_ENDPOINT, 2174fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_GET_STATUS, 2175fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij USB_FEATURE_HALT, 2176fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ep, 2177fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) status, 2178fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2, 2179fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 2180fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2181