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 800a576519a2e7157611266a74e61b9aedf4068b69Philip Langdalestruct ptp_event_cb_data { 810a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale PTPEventCbFn cb; 820a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale void *user_data; 830a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale PTPParams *params; 840a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale}; 850a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 86fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic const LIBMTP_device_entry_t mtp_device_table[] = { 87fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* We include an .h file which is shared between us and libgphoto2 */ 88fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#include "music-players.h" 89fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij}; 9011cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic const int mtp_device_table_size = 9111cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij sizeof(mtp_device_table) / sizeof(LIBMTP_device_entry_t); 92fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 93fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij// Local functions 943df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhangstatic LIBMTP_error_number_t init_usb(); 95fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void close_usb(PTP_USB* ptp_usb); 96fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int find_interface_and_endpoints(libusb_device *dev, 9715d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *conf, 98fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t *interface, 9915d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *altsetting, 100fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep, 101fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep_maxpacket, 102fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* outep, 103fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* outep_maxpacket, 104fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* intep); 105fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void clear_stall(PTP_USB* ptp_usb); 10611cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic int init_ptp_usb(PTPParams* params, 10711cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij PTP_USB* ptp_usb, libusb_device* dev); 10811cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic short ptp_write_func(unsigned long, 10911cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij PTPDataHandler*, void *data, unsigned long*); 11011cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic short ptp_read_func (unsigned long, 11111cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij PTPDataHandler*, void *data, unsigned long*, int); 11211cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijstatic int usb_get_endpoint_status(PTP_USB* ptp_usb, 11311cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij int ep, uint16_t* status); 114fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 115fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 116fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Get a list of the supported USB devices. 117fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 118fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * The developers depend on users of this library to constantly 119fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * add in to the list of supported devices. What we need is the 120fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * device name, USB Vendor ID (VID) and USB Product ID (PID). 121fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * put this into a bug ticket at the project homepage, please. 122fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * The VID/PID is used to let e.g. udev lift the device to 123fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * console userspace access when it's plugged in. 124fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 125fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param devices a pointer to a pointer that will hold a device 126fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * list after the call to this function, if it was 127fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * successful. 128fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param numdevs a pointer to an integer that will hold the number 129fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of devices in the device list if the call was successful. 130fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 0 if the list was successfull retrieved, any other 131fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * value means failure. 132fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 13311cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleijint LIBMTP_Get_Supported_Devices_List(LIBMTP_device_entry_t ** const devices, 13411cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij int * const numdevs) 135fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 136fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = (LIBMTP_device_entry_t *) &mtp_device_table; 137fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = mtp_device_table_size; 138fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 139fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 140fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 141fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1423df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhangstatic LIBMTP_error_number_t init_usb() 143fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 144468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner static int libusb1_initialized = 0; 145468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner 146fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 147fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Some additional libusb debugging please. 148fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We use the same level debug between MTP and USB. 149fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 150468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner if (libusb1_initialized) 151468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner return LIBMTP_ERROR_NONE; 152468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner 1533df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (libusb_init(NULL) < 0) { 1543df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_ERROR("Libusb1 init failed\n"); 1553df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return LIBMTP_ERROR_USB_LAYER; 1563df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang } 157fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 158468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner libusb1_initialized = 1; 159468e06b16c9aa87d90cb0ba7e75698038255540bMarcus Meissner 160fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((LIBMTP_debug & LIBMTP_DEBUG_USB) != 0) 161fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_set_debug(NULL,9); 1623df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return LIBMTP_ERROR_NONE; 163fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 164fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 165fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 16611cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * Small recursive function to append a new usb_device to the linked 16711cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * list of USB MTP devices 16811cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * @param devlist dynamic linked list of pointers to usb devices with 16911cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * MTP properties, to be extended with new device. 170fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param newdevice the new device to add. 171fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param bus_location bus for this device. 172fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return an extended array or NULL on failure. 173fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 174fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic mtpdevice_list_t *append_to_mtpdevice_list(mtpdevice_list_t *devlist, 175fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *newdevice, 176fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint32_t bus_location) 177fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 178fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *new_list_entry; 179fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 180fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry = (mtpdevice_list_t *) malloc(sizeof(mtpdevice_list_t)); 181fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (new_list_entry == NULL) { 182fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return NULL; 183fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 184fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Fill in USB device, if we *HAVE* to make a copy of the device do it here. 185fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry->device = newdevice; 186fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry->bus_location = bus_location; 187fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij new_list_entry->next = NULL; 188fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 189fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (devlist == NULL) { 190fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return new_list_entry; 191fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 192fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *tmp = devlist; 193fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (tmp->next != NULL) { 194fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tmp = tmp->next; 195fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 196fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tmp->next = new_list_entry; 197fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 198fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return devlist; 199fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 200fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 201fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 202fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Small recursive function to free dynamic memory allocated to the linked list 203fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of USB MTP devices 204fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param devlist dynamic linked list of pointers to usb devices with MTP 205fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * properties. 206fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return nothing 207fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 208fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void free_mtpdevice_list(mtpdevice_list_t *devlist) 209fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 210fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *tmplist = devlist; 211fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 212fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (devlist == NULL) 213fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return; 214fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (tmplist != NULL) { 215fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *tmp = tmplist; 216fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tmplist = tmplist->next; 217fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Do not free() the fields (ptp_usb, params)! These are used elsewhere. 218fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free(tmp); 219fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 220fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return; 221fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 222fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 223fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 224fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This checks if a device has an MTP descriptor. The descriptor was 225fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * elaborated about in gPhoto bug 1482084, and some official documentation 226fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * with no strings attached was published by Microsoft at 227fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://www.microsoft.com/whdc/system/bus/USB/USBFAQ_intermed.mspx#E3HAC 228fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 229fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param dev a device struct from libusb. 230fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param dumpfile set to non-NULL to make the descriptors dump out 231fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to this file in human-readable hex so we can scruitinze them. 232fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 1 if the device is MTP compliant, 0 if not. 233fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 234fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int probe_device_descriptor(libusb_device *dev, FILE *dumpfile) 235fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 236fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device_handle *devh; 237fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char buf[1024], cmd; 238fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i; 239fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 240fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* This is to indicate if we find some vendor interface */ 241fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_vendor_spec_interface = 0; 242fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 243fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 244fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_device_descriptor (dev, &desc); 245fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) return 0; 246fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 247fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Don't examine devices that are not likely to 248fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * contain any MTP interface, update this the day 249fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * you find some weird combination... 250fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 25126ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (!(desc.bDeviceClass == LIBUSB_CLASS_PER_INTERFACE || 25226ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij desc.bDeviceClass == LIBUSB_CLASS_COMM || 25326ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij desc.bDeviceClass == LIBUSB_CLASS_PTP || 254fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.bDeviceClass == 0xEF || /* Intf. Association Desc.*/ 25526ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij desc.bDeviceClass == LIBUSB_CLASS_VENDOR_SPEC)) { 256fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 257fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 258fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 259bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij /* 260bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * Attempt to open Device on this port 261bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * 262bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * TODO: is there a way to check the number of endpoints etc WITHOUT 263bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * opening the device? Some color calibration devices are REALLY 264bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * sensitive to this, and I found a Canon custom scanner that doesn't 265bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * like it at all either :-( 266bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij */ 267fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_open(dev, &devh); 268fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 269fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Could not open this device */ 270fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 271fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 272fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 273fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 274fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Loop over the device configurations and interfaces. Nokia MTP-capable 275fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * handsets (possibly others) typically have the string "MTP" in their 276fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * MTP interface descriptions, that's how they can be detected, before 277fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * we try the more esoteric "OS descriptors" (below). 278fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 279fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < desc.bNumConfigurations; i++) { 280fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t j; 281fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_config_descriptor *config; 282fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 283fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_config_descriptor (dev, i, &config); 284fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 285fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("configdescriptor %d get failed with ret %d in probe_device_descriptor yet dev->descriptor.bNumConfigurations > 0\n", i, ret); 286fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 287fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 288fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 289fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (j = 0; j < config->bNumInterfaces; j++) { 290fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int k; 291fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (k = 0; k < config->interface[j].num_altsetting; k++) { 292fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Current interface descriptor */ 293fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij const struct libusb_interface_descriptor *intf = 294fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &config->interface[j].altsetting[k]; 295fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 296fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 297fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * MTP interfaces have three endpoints, two bulk and one 298fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * interrupt. Don't probe anything else. 299fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 300fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (intf->bNumEndpoints != 3) 301fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 302fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 303fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 304fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We only want to probe for the OS descriptor if the 30526ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij * device is LIBUSB_CLASS_VENDOR_SPEC or one of the interfaces 306fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * in it is, so flag if we find an interface like this. 307fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 30826ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (intf->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC) { 309fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found_vendor_spec_interface = 1; 310fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 311fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 312fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 31311cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * TODO: Check for Still Image Capture class with PIMA 15740 31411cc9a7d587d293353409d34f6062624a2b80dfcLinus Walleij * protocol, also known as PTP 315fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 316fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#if 0 31726ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (intf->bInterfaceClass == LIBUSB_CLASS_PTP 318fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij && intf->bInterfaceSubClass == 0x01 319fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij && intf->bInterfaceProtocol == 0x01) { 320fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL) { 32115d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(dumpfile, "Configuration %d, interface %d, altsetting %d:\n", i, j, k); 322fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, " Found PTP device, check vendor " 323fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "extension...\n"); 324fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 325bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij /* 326bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * This is where we may insert code to open a PTP 327bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * session and query the vendor extension ID to see 328bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij * if it is 0xffffffff, i.e. MTP according to the spec. 329bda39ab9dec06c34236d1d7b01492fe13ca3d595Linus Walleij */ 330fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (was_mtp_extension) { 331fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 332fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 333fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 334fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 335fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#endif 336fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 337fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 338fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Next we search for the MTP substring in the interface name. 339fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * For example : "RIM MS/MTP" should work. 340fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 341fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf[0] = '\0'; 342fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_string_descriptor_ascii(devh, 343fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij config->interface[j].altsetting[k].iInterface, 344fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf, 345fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1024); 346fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < 3) 347fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 348fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (strstr((char *) buf, "MTP") != NULL) { 349fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL) { 350fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Configuration %d, interface %d, altsetting %d:\n", i, j, k); 351fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, " Interface description contains the string \"MTP\"\n"); 352fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, " Device recognized as MTP, no further probing.\n"); 353fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 35415d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 355fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 356fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 357fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 358fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (libusb_kernel_driver_active(devh, config->interface[j].altsetting[k].iInterface)) 359fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 360fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 361fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Specifically avoid probing anything else than USB mass storage devices 362fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * and non-associated drivers in Linux. 363fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 36426ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (config->interface[j].altsetting[k].bInterfaceClass != 36526ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij LIBUSB_CLASS_MASS_STORAGE) { 366fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("avoid probing device using attached kernel interface\n"); 36715d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 368be4a1b25d1bf8df0f9ae15d7aa0a89d2877120cdLinus Walleij libusb_close(devh); 369fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 370fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 371fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 372fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 37315d18e31458be5006eb229df68869df2fff93495Linus Walleij } 37415d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 37515d18e31458be5006eb229df68869df2fff93495Linus Walleij } 376fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 377fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 378fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Only probe for OS descriptor if the device is vendor specific 379fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * or one of the interfaces found is. 380fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 38126ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (desc.bDeviceClass == LIBUSB_CLASS_VENDOR_SPEC || 382fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found_vendor_spec_interface) { 383fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 384fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Read the special descriptor */ 385fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_descriptor(devh, 0x03, 0xee, buf, sizeof(buf)); 386fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 387fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 388fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * If something failed we're probably stalled to we need 389fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to clear the stall off the endpoint and say this is not 390fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * MTP. 391fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 392fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < 0) { 393fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* EP0 is the default control endpoint */ 3941165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner libusb_clear_halt (devh, 0); 395fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 396fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 397fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 398fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 399fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Dump it, if requested 400fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL && ret > 0) { 401fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Microsoft device descriptor 0xee:\n"); 402fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij data_dump_ascii(dumpfile, buf, ret, 16); 403fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 404fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 405fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if descriptor length is at least 10 bytes */ 406fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < 10) { 407fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 408fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 409fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 410fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 411fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if this device has a Microsoft Descriptor */ 412fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!((buf[2] == 'M') && (buf[4] == 'S') && 413fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (buf[6] == 'F') && (buf[8] == 'T'))) { 414fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 415fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 416fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 417fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 418fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if device responds to control message 1 or if there is an error */ 419fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij cmd = buf[16]; 420fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer (devh, 421fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR, 422fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij cmd, 423fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 424fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 4, 425fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf, 426fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(buf), 427fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij USB_TIMEOUT_DEFAULT); 428fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 429fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Dump it, if requested 430fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL && ret > 0) { 431fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Microsoft device response to control message 1, CMD 0x%02x:\n", cmd); 432fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij data_dump_ascii(dumpfile, buf, ret, 16); 433fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 434fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 435fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If this is true, the device either isn't MTP or there was an error */ 436fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret <= 0x15) { 437fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* TODO: If there was an error, flag it and let the user know somehow */ 438fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* if(ret == -1) {} */ 439fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 440fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 441fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 442fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 443fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Check if device is MTP or if it is something like a USB Mass Storage 444fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij device with Janus DRM support */ 445fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) { 446fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 447fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 448fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 449fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 450fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* After this point we are probably dealing with an MTP device */ 451fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 452fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 453fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Check if device responds to control message 2, which is 454fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * the extended device parameters. Most devices will just 455fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * respond with a copy of the same message as for the first 456fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * message, some respond with zero-length (which is OK) 457fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * and some with pure garbage. We're not parsing the result 458fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * so this is not very important. 459fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 460fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer (devh, 461fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR, 462fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij cmd, 463fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 464fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 5, 465fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buf, 466fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(buf), 467fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij USB_TIMEOUT_DEFAULT); 468fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 469fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Dump it, if requested 470fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dumpfile != NULL && ret > 0) { 471fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Microsoft device response to control message 2, CMD 0x%02x:\n", cmd); 472fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij data_dump_ascii(dumpfile, buf, ret, 16); 473fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 474fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 475fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If this is true, the device errored against control message 2 */ 476fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret == -1) { 477fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* TODO: Implement callback function to let managing program know there 478fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij was a problem, along with description of the problem */ 479fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("Potential MTP Device with VendorID:%04x and " 480fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "ProductID:%04x encountered an error responding to " 481fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "control message 2.\n" 482fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "Problems may arrise but continuing\n", 483fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idVendor, desc.idProduct); 484fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (dumpfile != NULL && ret == 0) { 485fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Zero-length response to control message 2 (OK)\n"); 486fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (dumpfile != NULL) { 487fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf(dumpfile, "Device responds to control message 2 with some data.\n"); 488fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 489fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Close the USB device handle */ 490fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 491fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 492fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 493fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 494fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Close the USB device handle */ 495fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(devh); 496fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 497fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 498fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 499fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 500fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This function scans through the connected usb devices on a machine and 501fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * if they match known Vendor and Product identifiers appends them to the 502fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * dynamic array mtp_device_list. Be sure to call 503fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * <code>free_mtpdevice_list(mtp_device_list)</code> when you are done 504fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * with it, assuming it is not NULL. 505fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param mtp_device_list dynamic array of pointers to usb devices with MTP 506fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * properties (if this list is not empty, new entries will be appended 507fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to the list). 508fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return LIBMTP_ERROR_NONE implies that devices have been found, scan the list 509fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * appropriately. LIBMTP_ERROR_NO_DEVICE_ATTACHED implies that no 510fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * devices have been found. 511fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 512fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic LIBMTP_error_number_t get_mtp_usb_device_list(mtpdevice_list_t ** mtp_device_list) 513fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 514fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ssize_t nrofdevs; 515fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device **devs = NULL; 516fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret, i; 5173df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_error_number_t init_usb_ret; 518fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 5193df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang init_usb_ret = init_usb(); 5203df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (init_usb_ret != LIBMTP_ERROR_NONE) 5213df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return init_usb_ret; 522fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 523fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij nrofdevs = libusb_get_device_list (NULL, &devs); 524fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < nrofdevs ; i++) { 525fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *dev = devs[i]; 526fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 527fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 528fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_get_device_descriptor(dev, &desc); 529fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) continue; 530fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 53126ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if (desc.bDeviceClass != LIBUSB_CLASS_HUB) { 532fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i; 533fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found = 0; 534fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 535fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // First check if we know about the device already. 536fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Devices well known to us will not have their descriptors 537fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // probed, it caused problems with some devices. 538fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for(i = 0; i < mtp_device_table_size; i++) { 539fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(desc.idVendor == mtp_device_table[i].vendor_id && 540fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct == mtp_device_table[i].product_id) { 541fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Append this usb device to the MTP device list */ 542fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *mtp_device_list = append_to_mtpdevice_list(*mtp_device_list, 543fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev, 544fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_bus_number(dev)); 545fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found = 1; 546fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 547fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 548fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 549fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // If we didn't know it, try probing the "OS Descriptor". 550fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!found) { 551fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (probe_device_descriptor(dev, NULL)) { 552fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Append this usb device to the MTP USB Device List */ 553fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *mtp_device_list = append_to_mtpdevice_list(*mtp_device_list, 554fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev, 555fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_bus_number(dev)); 556fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 557fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 558fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * By thomas_-_s: Also append devices that are no MTP but PTP devices 559fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * if this is commented out. 560fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 561fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 562fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else { 563fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Check whether the device is no USB hub but a PTP. 56426ceac867dc93babdb17e2d1bd9ee947802afce9Linus Walleij if ( dev->config != NULL &&dev->config->interface->altsetting->bInterfaceClass == LIBUSB_CLASS_PTP && dev->descriptor.bDeviceClass != LIBUSB_CLASS_HUB ) { 565fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *mtp_device_list = append_to_mtpdevice_list(*mtp_device_list, dev, bus->location); 566fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 567fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 568fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 569fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 570fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 571fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 5721e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 573fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 574fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If nothing was found we end up here. */ 575fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(*mtp_device_list == NULL) { 576fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NO_DEVICE_ATTACHED; 577fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 578fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 579fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 580fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 581fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 582fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Checks if a specific device with a certain bus and device 583fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * number has an MTP type device descriptor. 584fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 585fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param busno the bus number of the device to check 586fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param deviceno the device number of the device to check 587fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 1 if the device is MTP else 0 588fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 589fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijint LIBMTP_Check_Specific_Device(int busno, int devno) 590fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 591fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ssize_t nrofdevs; 592fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device **devs = NULL; 593fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i; 5943df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_error_number_t init_usb_ret; 595fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 5963df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang init_usb_ret = init_usb(); 5973df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (init_usb_ret != LIBMTP_ERROR_NONE) 5983df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return 0; 599fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 600fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij nrofdevs = libusb_get_device_list (NULL, &devs); 601fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < nrofdevs ; i++ ) { 60230f9acdc94c087209d3feb80bf545ce3cf1033a0Jonas Salling if (libusb_get_bus_number(devs[i]) != busno) 6033e0a71ce369bc970a90b6d90301120359d769772Marcus Meissner continue; 60430f9acdc94c087209d3feb80bf545ce3cf1033a0Jonas Salling if (libusb_get_device_address(devs[i]) != devno) 6053e0a71ce369bc970a90b6d90301120359d769772Marcus Meissner continue; 6063e0a71ce369bc970a90b6d90301120359d769772Marcus Meissner if (probe_device_descriptor(devs[i], NULL)) 607fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 1; 608fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 609fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 610fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 611fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 612fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 613fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Detect the raw MTP device descriptors and return a list of 614fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of the devices found. 615fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 616fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param devices a pointer to a variable that will hold 617fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * the list of raw devices found. This may be NULL 618fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * on return if the number of detected devices is zero. 619fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * The user shall simply <code>free()</code> this 620fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * variable when finished with the raw devices, 621fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * in order to release memory. 622fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param numdevs a pointer to an integer that will hold 623fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * the number of devices in the list. This may 624fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * be 0. 625fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return 0 if successful, any other value means failure. 626fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 627fbbef8b16876568f760986e4ff8f4921b8373fd5Linus WalleijLIBMTP_error_number_t LIBMTP_Detect_Raw_Devices(LIBMTP_raw_device_t ** devices, 628fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int * numdevs) 629fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 630fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *devlist = NULL; 631fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtpdevice_list_t *dev; 632fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_error_number_t ret; 633fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_raw_device_t *retdevs; 634fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int devs = 0; 635fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int i, j; 636fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 637fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = get_mtp_usb_device_list(&devlist); 638fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret == LIBMTP_ERROR_NO_DEVICE_ATTACHED) { 639fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = NULL; 640fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = 0; 641fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 642fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (ret != LIBMTP_ERROR_NONE) { 643fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: get_mtp_usb_device_list() " 644fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "error code: %d on line %d\n", ret, __LINE__); 645fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 646fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 647fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 648fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Get list size 649fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = devlist; 650fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (dev != NULL) { 651fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij devs++; 652fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = dev->next; 653fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 654fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (devs == 0) { 655fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = NULL; 656fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = 0; 657fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 658fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 659fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Conjure a device list 660fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs = (LIBMTP_raw_device_t *) malloc(sizeof(LIBMTP_raw_device_t) * devs); 661fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (retdevs == NULL) { 662fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Out of memory 663fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = NULL; 664fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = 0; 665fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_MEMORY_ALLOCATION; 666fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 667fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = devlist; 668fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij i = 0; 669fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (dev != NULL) { 670fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int device_known = 0; 671fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 672fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 673fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_device_descriptor (dev->device, &desc); 674fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Assign default device info 675fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.vendor = NULL; 676fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.vendor_id = desc.idVendor; 677fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.product = NULL; 678fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.product_id = desc.idProduct; 679fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.device_flags = 0x00000000U; 680fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // See if we can locate some additional vendor info and device flags 681fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for(j = 0; j < mtp_device_table_size; j++) { 682fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(desc.idVendor == mtp_device_table[j].vendor_id && 683fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct == mtp_device_table[j].product_id) { 684fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij device_known = 1; 685fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.vendor = mtp_device_table[j].vendor; 686fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.product = mtp_device_table[j].product; 687fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].device_entry.device_flags = mtp_device_table[j].device_flags; 688fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 689fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This device is known to the developers 690fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("Device %d (VID=%04x and PID=%04x) is a %s %s.\n", 691fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij i, 692fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idVendor, 693fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct, 694fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtp_device_table[j].vendor, 695fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij mtp_device_table[j].product); 696fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 697fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 698fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 699fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!device_known) { 700524e42caee22313738733a3e4ee74acdb5e561b7Andrés G. Aragoneses device_unknown(i, desc.idVendor, desc.idProduct); 701fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 702fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Save the location on the bus 703fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].bus_location = libusb_get_bus_number (dev->device); 704fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij retdevs[i].devnum = libusb_get_device_address (dev->device); 705fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij i++; 706fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = dev->next; 707fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 708fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *devices = retdevs; 709fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *numdevs = i; 710fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free_mtpdevice_list(devlist); 711fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 712fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 713fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 714fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 715fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This routine just dumps out low-level 716fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * USB information about the current device. 717fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param ptp_usb the USB device to get information from. 718fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 719fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid dump_usbinfo(PTP_USB *ptp_usb) 720fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 721fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *dev; 722fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 723fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 724fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (libusb_kernel_driver_active(ptp_usb->handle, ptp_usb->interface)) 725fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Interface has a kernel driver attached.\n"); 726fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 727fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = libusb_get_device (ptp_usb->handle); 728fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_device_descriptor (dev, &desc); 729fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 730fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bcdUSB: %d\n", desc.bcdUSB); 731fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bDeviceClass: %d\n", desc.bDeviceClass); 732fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bDeviceSubClass: %d\n", desc.bDeviceSubClass); 733fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" bDeviceProtocol: %d\n", desc.bDeviceProtocol); 734fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" idVendor: %04x\n", desc.idVendor); 735fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" idProduct: %04x\n", desc.idProduct); 736fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" IN endpoint maxpacket: %d bytes\n", ptp_usb->inep_maxpacket); 737fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" OUT endpoint maxpacket: %d bytes\n", ptp_usb->outep_maxpacket); 738fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Raw device info:\n"); 739fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Bus location: %d\n", ptp_usb->rawdevice.bus_location); 740fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Device number: %d\n", ptp_usb->rawdevice.devnum); 741fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Device entry info:\n"); 742fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Vendor: %s\n", ptp_usb->rawdevice.device_entry.vendor); 743fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Vendor id: 0x%04x\n", ptp_usb->rawdevice.device_entry.vendor_id); 744fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Product: %s\n", ptp_usb->rawdevice.device_entry.product); 745fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Vendor id: 0x%04x\n", ptp_usb->rawdevice.device_entry.product_id); 746fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO(" Device flags: 0x%08x\n", ptp_usb->rawdevice.device_entry.device_flags); 747fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (void) probe_device_descriptor(dev, stdout); 748fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 749fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 750fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 751fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Retrieve the apropriate playlist extension for this 752fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * device. Rather hacky at the moment. This is probably 753fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * desired by the managing software, but when creating 754fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * lists on the device itself you notice certain preferences. 755fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param ptp_usb the USB device to get suggestion for. 756fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return the suggested playlist extension. 757fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 758fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijconst char *get_playlist_extension(PTP_USB *ptp_usb) 759fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 760fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *dev; 761fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 762fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij static char creative_pl_extension[] = ".zpl"; 763fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij static char default_pl_extension[] = ".pla"; 764fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 765fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij dev = libusb_get_device(ptp_usb->handle); 766fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_get_device_descriptor (dev, &desc); 767fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (desc.idVendor == 0x041e) 768fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return creative_pl_extension; 769fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return default_pl_extension; 770fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 771fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 772fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void 773fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijlibusb_glue_debug (PTPParams *params, const char *format, ...) 774fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 775fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_list args; 776fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 777fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_start (args, format); 778fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->debug_func!=NULL) 779fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->debug_func (params->data, format, args); 780fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 781fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 782fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij vfprintf (stderr, format, args); 783fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf (stderr,"\n"); 784fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fflush (stderr); 785fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 786fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_end (args); 787fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 788fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 789fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void 790fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijlibusb_glue_error (PTPParams *params, const char *format, ...) 791fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 792fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_list args; 793fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 794fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_start (args, format); 795fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->error_func!=NULL) 796fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->error_func (params->data, format, args); 797fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 798fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 799fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij vfprintf (stderr, format, args); 800fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fprintf (stderr,"\n"); 801fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij fflush (stderr); 802fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 803fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij va_end (args); 804fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 805fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 806fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 807fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* 808fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * ptp_read_func() and ptp_write_func() are 809fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * based on same functions usb.c in libgphoto2. 810fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Much reading packet logs and having fun with trials and errors 811fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * reveals that WMP / Windows is probably using an algorithm like this 812fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * for large transfers: 813fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 814fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 1. Send the command (0x0c bytes) if headers are split, else, send 815fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * command plus sizeof(endpoint) - 0x0c bytes. 816fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 2. Send first packet, max size to be sizeof(endpoint) but only when using 817fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * split headers. Else goto 3. 818fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 3. REPEAT send 0x10000 byte chunks UNTIL remaining bytes < 0x10000 819fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We call 0x10000 CONTEXT_BLOCK_SIZE. 820fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 4. Send remaining bytes MOD sizeof(endpoint) 821fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 5. Send remaining bytes. If this happens to be exactly sizeof(endpoint) 822fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * then also send a zero-length package. 823fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 824fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Further there is some special quirks to handle zero reads from the 825fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * device, since some devices can't do them at all due to shortcomings 826fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * of the USB slave controller in the device. 827fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 828fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define CONTEXT_BLOCK_SIZE_1 0x3e00 829fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define CONTEXT_BLOCK_SIZE_2 0x200 830fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define CONTEXT_BLOCK_SIZE CONTEXT_BLOCK_SIZE_1+CONTEXT_BLOCK_SIZE_2 831fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic short 832fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_read_func ( 833fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long size, PTPDataHandler *handler,void *data, 834fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long *readbytes, 835fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int readzero 836fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 837fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)data; 838fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long toread = 0; 839fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret = 0; 840fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int xread; 841fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long curread = 0; 842fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *bytes; 843fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int expect_terminator_byte = 0; 8444a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long usb_inep_maxpacket_size; 8454a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long context_block_size_1; 8464a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long context_block_size_2; 8474a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu uint16_t ptp_dev_vendor_id = ptp_usb->rawdevice.device_entry.vendor_id; 8484a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu 8494a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu //"iRiver" device special handling 8504a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu if (ptp_dev_vendor_id == 0x4102 || ptp_dev_vendor_id == 0x1006) { 8514a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu usb_inep_maxpacket_size = ptp_usb->inep_maxpacket; 8524a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu if (usb_inep_maxpacket_size == 0x400) { 8534a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_1 = CONTEXT_BLOCK_SIZE_1 - 0x200; 8544a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_2 = CONTEXT_BLOCK_SIZE_2 + 0x200; 8554a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 8564a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else { 8574a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_1 = CONTEXT_BLOCK_SIZE_1; 8584a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu context_block_size_2 = CONTEXT_BLOCK_SIZE_2; 8594a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 8604a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 861fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This is the largest block we'll need to read in. 862fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes = malloc(CONTEXT_BLOCK_SIZE); 863fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (curread < size) { 864fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 865fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Remaining size to read: 0x%04lx bytes\n", size - curread); 866fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 867fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // check equal to condition here 868fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (size - curread < CONTEXT_BLOCK_SIZE) 869fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 870fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // this is the last packet 871fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij toread = size - curread; 872fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // this is equivalent to zero read for these devices 873fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (readzero && FLAG_NO_ZERO_READS(ptp_usb) && toread % 64 == 0) { 874fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij toread += 1; 875fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij expect_terminator_byte = 1; 876fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 877fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 8784a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else if (ptp_dev_vendor_id == 0x4102 || ptp_dev_vendor_id == 0x1006) { 8794a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu //"iRiver" device special handling 8804a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu if (curread == 0) 8814a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu // we are first packet, but not last packet 8824a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = context_block_size_1; 8834a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else if (toread == context_block_size_1) 8844a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = context_block_size_2; 8854a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else if (toread == context_block_size_2) 8864a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = context_block_size_1; 8874a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu else 8884a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu LIBMTP_INFO("unexpected toread size 0x%04x, 0x%04x remaining bytes\n", 8894a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu (unsigned int) toread, (unsigned int) (size-curread)); 8904a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu } 891fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 8924a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu toread = CONTEXT_BLOCK_SIZE; 893fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 894fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Reading in 0x%04lx bytes\n", toread); 895fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 896fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = USB_BULK_READ(ptp_usb->handle, 897fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 898fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes, 899fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij toread, 900fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 901fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 902fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 903fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Result of read: 0x%04x (%d bytes)\n", ret, xread); 904fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 905fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) 906fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 907fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 908fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("<==USB IN\n"); 909fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xread == 0) 910fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Zero Read\n"); 911fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij else 912fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(bytes, xread, 16); 913fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 914fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // want to discard extra byte 915fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (expect_terminator_byte && xread == toread) 916fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij { 917fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("<==USB IN\nDiscarding extra byte\n"); 918fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 919fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij xread--; 920fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 921fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 9223d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner int putfunc_ret = handler->putfunc(NULL, handler->priv, xread, bytes); 923fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (putfunc_ret != PTP_RC_OK) 924fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return putfunc_ret; 925fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 926fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete += xread; 927fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij curread += xread; 928fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 929fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Increase counters, call callback 930fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->callback_active) { 931fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_complete >= ptp_usb->current_transfer_total) { 932fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // send last update and disable callback. 933fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete = ptp_usb->current_transfer_total; 934fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->callback_active = 0; 935fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 936fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_callback != NULL) { 937fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 938fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb->current_transfer_callback(ptp_usb->current_transfer_complete, 939fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_total, 940fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_callback_data); 941fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != 0) { 942fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_CANCEL; 943fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 944fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 945fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 946fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 947fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xread < toread) /* short reads are common */ 948fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 949fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 950fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (readbytes) *readbytes = curread; 951fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (bytes); 952fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 953fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // there might be a zero packet waiting for us... 954fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (readzero && 955fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij !FLAG_NO_ZERO_READS(ptp_usb) && 956fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij curread % ptp_usb->outep_maxpacket == 0) { 957fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char temp; 958fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int zeroresult = 0, xread; 959fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 960fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("<==USB IN\n"); 961fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Zero Read\n"); 962fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 963fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij zeroresult = USB_BULK_READ(ptp_usb->handle, 964fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 965fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &temp, 966fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 967fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 968fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 969fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (zeroresult != LIBUSB_SUCCESS) 970fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("LIBMTP panic: unable to read in zero packet, response 0x%04x", zeroresult); 971fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 972fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 973fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 974fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 975fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 976fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic short 977fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_write_func ( 978fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long size, 979fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler *handler, 980fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij void *data, 981fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long *written 982fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 983fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)data; 984fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long towrite = 0; 985fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret = 0; 986fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long curwrite = 0; 987fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *bytes; 988fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 989fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This is the largest block we'll need to read in. 990fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes = malloc(CONTEXT_BLOCK_SIZE); 991fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!bytes) { 992fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 993fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 994fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (curwrite < size) { 995fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long usbwritten = 0; 996c4b6a194d19c31f9cfcf4c12dddf803037aa01b3Marcus Meissner int xwritten = 0; 997fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 998fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite = size-curwrite; 999fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (towrite > CONTEXT_BLOCK_SIZE) { 1000fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite = CONTEXT_BLOCK_SIZE; 1001fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 1002fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This magic makes packets the same size that WMP send them. 1003fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (towrite > ptp_usb->outep_maxpacket && towrite % ptp_usb->outep_maxpacket != 0) { 1004fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite -= towrite % ptp_usb->outep_maxpacket; 1005fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1006fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1007fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int getfunc_ret = handler->getfunc(NULL, handler->priv,towrite,bytes,&towrite); 10081e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang if (getfunc_ret != PTP_RC_OK) { 10091e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang free(bytes); 1010fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return getfunc_ret; 10111e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang } 1012fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (usbwritten < towrite) { 1013fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = USB_BULK_WRITE(ptp_usb->handle, 1014fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->outep, 1015fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes+usbwritten, 1016fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite-usbwritten, 1017fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xwritten, 1018fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1019fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1020fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("USB OUT==>\n"); 1021fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1022fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 10231e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang free(bytes); 1024fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1025fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1026fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(bytes+usbwritten, xwritten, 16); 1027fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // check for result == 0 perhaps too. 1028fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Increase counters 1029fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete += xwritten; 1030fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij curwrite += xwritten; 1031fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbwritten += xwritten; 1032fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1033fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // call callback 1034fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->callback_active) { 1035fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_complete >= ptp_usb->current_transfer_total) { 1036fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // send last update and disable callback. 1037fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_complete = ptp_usb->current_transfer_total; 1038fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->callback_active = 0; 1039fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1040fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_callback != NULL) { 1041fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1042fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb->current_transfer_callback(ptp_usb->current_transfer_complete, 1043fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_total, 1044fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->current_transfer_callback_data); 1045fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != 0) { 10461e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang free(bytes); 1047fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_CANCEL; 1048fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1049fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1050fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1051fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xwritten < towrite) /* short writes happen */ 1052fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1053fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1054fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (bytes); 1055fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (written) { 1056fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *written = curwrite; 1057fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1058fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1059fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // If this is the last transfer send a zero write if required 1060fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb->current_transfer_complete >= ptp_usb->current_transfer_total) { 1061fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((towrite % ptp_usb->outep_maxpacket) == 0) { 1062fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int xwritten; 1063fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1064fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("USB OUT==>\n"); 1065fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Zero Write\n"); 1066fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1067fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret =USB_BULK_WRITE(ptp_usb->handle, 1068fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->outep, 1069fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) "x", 1070fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 1071fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xwritten, 1072fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1073fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1074fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1075fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1076fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) 1077fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1078fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1079fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1080fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1081fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* memory data get/put handler */ 1082fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijtypedef struct { 1083fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *data; 1084fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long size, curoff; 1085fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} PTPMemHandlerPrivate; 1086fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1087fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1088fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijmemory_getfunc(PTPParams* params, void* private, 1089fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long wantlen, unsigned char *data, 1090fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long *gotlen 1091fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1092fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private; 1093fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long tocopy = wantlen; 1094fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1095fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (priv->curoff + tocopy > priv->size) 1096fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij tocopy = priv->size - priv->curoff; 1097fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy (data, priv->data + priv->curoff, tocopy); 1098fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff += tocopy; 1099fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *gotlen = tocopy; 1100fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1101fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1102fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1103fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1104fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijmemory_putfunc(PTPParams* params, void* private, 11053d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner unsigned long sendlen, unsigned char *data 1106fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1107fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)private; 1108fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1109fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (priv->curoff + sendlen > priv->size) { 1110fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->data = realloc (priv->data, priv->curoff+sendlen); 1111fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->size = priv->curoff + sendlen; 1112fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1113fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy (priv->data + priv->curoff, data, sendlen); 1114fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff += sendlen; 1115fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1116fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1117fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1118fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* init private struct for receiving data. */ 1119fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1120fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_init_recv_memory_handler(PTPDataHandler *handler) { 1121fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv; 1122fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv = malloc (sizeof(PTPMemHandlerPrivate)); 1123fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->priv = priv; 1124fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->getfunc = memory_getfunc; 1125fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc = memory_putfunc; 1126fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->data = NULL; 1127fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->size = 0; 1128fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff = 0; 1129fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1130fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1131fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1132fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* init private struct and put data in for sending data. 1133fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * data is still owned by caller. 1134fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1135fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1136fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_init_send_memory_handler(PTPDataHandler *handler, 1137fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *data, unsigned long len 1138fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1139fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv; 1140fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv = malloc (sizeof(PTPMemHandlerPrivate)); 1141fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!priv) 1142fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_GeneralError; 1143fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->priv = priv; 1144fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->getfunc = memory_getfunc; 1145fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc = memory_putfunc; 1146fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->data = data; 1147fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->size = len; 1148fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij priv->curoff = 0; 1149fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1150fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1151fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1152fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* free private struct + data */ 1153fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1154fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_exit_send_memory_handler (PTPDataHandler *handler) { 1155fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv; 1156fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* data is owned by caller */ 1157fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (priv); 1158fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1159fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1160fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1161fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* hand over our internal data to caller */ 1162fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t 1163fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_exit_recv_memory_handler (PTPDataHandler *handler, 1164fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char **data, unsigned long *size 1165fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1166fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPMemHandlerPrivate* priv = (PTPMemHandlerPrivate*)handler->priv; 1167fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *data = priv->data; 1168fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *size = priv->size; 1169fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (priv); 1170fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1171fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1172fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1173fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* send / receive functions */ 1174fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1175fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 11763d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerptp_usb_sendreq (PTPParams* params, PTPContainer* req, int dataphase) 1177fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1178fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1179fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbreq; 1180fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler memhandler; 1181fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long written = 0; 1182fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long towrite; 1183fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1184f76b10a24ae1d4f63ca92310263b841e117c9246Marcus Meissner LIBMTP_USB_DEBUG("REQUEST: 0x%04x, %s\n", req->Code, ptp_get_opcode_name(params, req->Code)); 1185fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1186fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build appropriate USB container */ 1187fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.length=htod32(PTP_USB_BULK_REQ_LEN- 1188fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (sizeof(uint32_t)*(5-req->Nparam))); 1189fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.type=htod16(PTP_USB_CONTAINER_COMMAND); 1190fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.code=htod16(req->Code); 1191fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.trans_id=htod32(req->Transaction_ID); 1192fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param1=htod32(req->Param1); 1193fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param2=htod32(req->Param2); 1194fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param3=htod32(req->Param3); 1195fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param4=htod32(req->Param4); 1196fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbreq.payload.params.param5=htod32(req->Param5); 1197fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* send it to responder */ 1198fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite = PTP_USB_BULK_REQ_LEN-(sizeof(uint32_t)*(5-req->Nparam)); 1199fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_init_send_memory_handler (&memhandler, (unsigned char*)&usbreq, towrite); 1200fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret=ptp_write_func( 1201fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij towrite, 1202fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &memhandler, 1203fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data, 1204fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &written 1205fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1206fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_exit_send_memory_handler (&memhandler); 1207fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK && ret != PTP_ERROR_CANCEL) { 1208fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1209fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1210fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (written != towrite && ret != PTP_ERROR_CANCEL && ret != PTP_ERROR_IO) { 1211fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_error (params, 1212fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: request code 0x%04x sending req wrote only %ld bytes instead of %d", 1213fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij req->Code, written, towrite 1214fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1215fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1216fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1217fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1218fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1219fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1220fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1221fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_senddata (PTPParams* params, PTPContainer* ptp, 1222b3aaade14e14a67419c3edf6367b50599eec134fLinus Walleij uint64_t size, PTPDataHandler *handler 1223fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij) { 1224fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1225fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int wlen, datawlen; 1226fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long written; 1227fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbdata; 12281a5fe0ae4de66d1ca97f7ae712d75b409b1a7841Philip Langdale uint64_t bytes_left_to_transfer; 1229fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler memhandler; 12306c016415c6bd986413088a330595786d7d3d358cJerry Zhang unsigned long packet_size; 12316c016415c6bd986413088a330595786d7d3d358cJerry Zhang PTP_USB *ptp_usb = (PTP_USB *) params->data; 12326c016415c6bd986413088a330595786d7d3d358cJerry Zhang 12336c016415c6bd986413088a330595786d7d3d358cJerry Zhang packet_size = ptp_usb->outep_maxpacket; 1234fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1235fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1236fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("SEND DATA PHASE\n"); 1237fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1238fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build appropriate USB container */ 1239fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.length = htod32(PTP_USB_BULK_HDR_LEN+size); 1240fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.type = htod16(PTP_USB_CONTAINER_DATA); 1241fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.code = htod16(ptp->Code); 1242fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.trans_id= htod32(ptp->Transaction_ID); 1243fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1244fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ((PTP_USB*)params->data)->current_transfer_complete = 0; 1245fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ((PTP_USB*)params->data)->current_transfer_total = size+PTP_USB_BULK_HDR_LEN; 1246fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1247fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->split_header_data) { 1248fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij datawlen = 0; 1249fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij wlen = PTP_USB_BULK_HDR_LEN; 1250fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 1251fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long gotlen; 1252fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* For all camera devices. */ 1253fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij datawlen = (size<PTP_USB_BULK_PAYLOAD_LEN_WRITE)?size:PTP_USB_BULK_PAYLOAD_LEN_WRITE; 1254fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij wlen = PTP_USB_BULK_HDR_LEN + datawlen; 1255fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1256fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = handler->getfunc(params, handler->priv, datawlen, usbdata.payload.data, &gotlen); 1257fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != PTP_RC_OK) 1258fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1259fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (gotlen != datawlen) 1260fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_GeneralError; 1261fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1262fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_init_send_memory_handler (&memhandler, (unsigned char *)&usbdata, wlen); 1263fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* send first part of data */ 1264fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_write_func(wlen, &memhandler, params->data, &written); 1265fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_exit_send_memory_handler (&memhandler); 1266fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1267fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1268fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1269fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (size <= datawlen) return ret; 1270fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* if everything OK send the rest */ 1271fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_left_to_transfer = size-datawlen; 1272fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_RC_OK; 1273fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while(bytes_left_to_transfer > 0) { 12746c016415c6bd986413088a330595786d7d3d358cJerry Zhang int max_long_transfer = ULONG_MAX + 1 - packet_size; 12756c016415c6bd986413088a330595786d7d3d358cJerry Zhang ret = ptp_write_func (bytes_left_to_transfer > max_long_transfer ? max_long_transfer : bytes_left_to_transfer, 12766c016415c6bd986413088a330595786d7d3d358cJerry Zhang handler, params->data, &written); 1277fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != PTP_RC_OK) 1278fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1279fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (written == 0) { 1280fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1281fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1282fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1283fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_left_to_transfer -= written; 1284fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1285fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK && ret != PTP_ERROR_CANCEL) 1286fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1287fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1288fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1289fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1290fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic uint16_t ptp_usb_getpacket(PTPParams *params, 1291fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer *packet, unsigned long *rlen) 1292fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1293fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPDataHandler memhandler; 1294fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1295fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char *x = NULL; 12964a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu unsigned long packet_size; 12974a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu PTP_USB *ptp_usb = (PTP_USB *) params->data; 12984a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu 12994a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu packet_size = ptp_usb->inep_maxpacket; 1300fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1301fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* read the header and potentially the first data */ 1302fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (params->response_packet_size > 0) { 1303fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* If there is a buffered packet, just use it. */ 1304fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy(packet, params->response_packet, params->response_packet_size); 1305fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *rlen = params->response_packet_size; 1306fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free(params->response_packet); 1307fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet = NULL; 1308fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet_size = 0; 1309fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Here this signifies a "virtual read" */ 1310fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1311fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1312fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_init_recv_memory_handler (&memhandler); 13134a9e6046319ad834b924031d74f50e58b88d7d84Yingxi Yu ret = ptp_read_func(packet_size, &memhandler, params->data, rlen, 0); 1314fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_exit_recv_memory_handler (&memhandler, &x, rlen); 1315fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (x) { 1316fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy (packet, x, *rlen); 1317fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij free (x); 1318fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1319fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1320fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1321fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1322fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1323fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler) 1324fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1325fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1326fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbdata; 1327fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *) params->data; 1328fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int putfunc_ret; 1329fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1330fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("GET DATA PHASE\n"); 1331fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1332fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(&usbdata,0,sizeof(usbdata)); 1333fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij do { 1334fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long len, rlen; 1335fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1336fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb_getpacket(params, &usbdata, &rlen); 1337fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1338fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1339fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1340fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1341fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbdata.type)!=PTP_USB_CONTAINER_DATA) { 1342fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_DATA_EXPECTED; 1343fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1344fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1345fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbdata.code)!=ptp->Code) { 1346fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_IGNORE_HEADER_ERRORS(ptp_usb)) { 1347fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp2/ptp_usb_getdata: detected a broken " 1348fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP header, code field insane, expect problems! (But continuing)"); 1349fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Repair the header, so it won't wreak more havoc, don't just ignore it. 1350fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Typically these two fields will be broken. 1351fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.code = htod16(ptp->Code); 1352fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbdata.trans_id = htod32(ptp->Transaction_ID); 1353fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_RC_OK; 1354fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else { 1355fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = dtoh16(usbdata.code); 1356fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This filters entirely insane garbage return codes, but still 1357fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // makes it possible to return error codes in the code field when 1358fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // getting data. It appears Windows ignores the contents of this 1359fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // field entirely. 1360fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < PTP_RC_Undefined || ret > PTP_RC_SpecificationOfDestinationUnsupported) { 1361fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp2/ptp_usb_getdata: detected a broken " 1362fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP header, code field insane."); 1363fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1364fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1365fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1366fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1367fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1368aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner if (rlen == ptp_usb->inep_maxpacket) { 1369fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy first part of data to 'data' */ 1370fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij putfunc_ret = 1371fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc( 13723d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, usbdata.payload.data 1373fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1374fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (putfunc_ret != PTP_RC_OK) 1375fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return putfunc_ret; 1376fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1377fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* stuff data directly to passed data handler */ 1378fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (1) { 1379fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long readdata; 1380fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t xret; 1381fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 13821165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner xret = ptp_read_func( 1383e6f7703dd1749504ed9060e1bc55f82ecc456af6Philip Langdale 0x20000000, 1384fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler, 1385fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data, 1386fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &readdata, 1387fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0 1388fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1389fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (xret != PTP_RC_OK) 1390fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return xret; 1391e6f7703dd1749504ed9060e1bc55f82ecc456af6Philip Langdale if (readdata < 0x20000000) 1392fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1393fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1394fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1395fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1396fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (rlen > dtoh32(usbdata.length)) { 1397fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1398fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Buffer the surplus response packet if it is >= 1399fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * PTP_USB_BULK_HDR_LEN 1400fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * (i.e. it is probably an entire package) 1401fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * else discard it as erroneous surplus data. 1402fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This will even work if more than 2 packets appear 1403fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * in the same transaction, they will just be handled 1404fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * iteratively. 1405fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * 1406fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Marcus observed stray bytes on iRiver devices; 1407fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * these are still discarded. 1408fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1409fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned int packlen = dtoh32(usbdata.length); 1410fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned int surplen = rlen - packlen; 1411fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1412fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (surplen >= PTP_USB_BULK_HDR_LEN) { 1413fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet = malloc(surplen); 1414fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy(params->response_packet, 1415fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (uint8_t *) &usbdata + packlen, surplen); 1416fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->response_packet_size = surplen; 1417fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Ignore reading one extra byte if device flags have been set */ 1418fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if(!FLAG_NO_ZERO_READS(ptp_usb) && 1419fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (rlen - dtoh32(usbdata.length) == 1)) { 1420fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp2/ptp_usb_getdata: read %d bytes " 1421fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "too much, expect problems!", 1422fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij rlen - dtoh32(usbdata.length)); 1423fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1424fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij rlen = packlen; 1425fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1426fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1427fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* For most PTP devices rlen is 512 == sizeof(usbdata) 1428fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * here. For MTP devices splitting header and data it might 1429fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * be 12. 1430fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1431fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Evaluate full data length. */ 1432fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij len=dtoh32(usbdata.length)-PTP_USB_BULK_HDR_LEN; 1433fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1434fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* autodetect split header/data MTP devices */ 1435fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh32(usbdata.length) > 12 && (rlen==12)) 1436fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->split_header_data = 1; 1437fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1438fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy first part of data to 'data' */ 1439fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij putfunc_ret = 1440fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler->putfunc( 1441fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, 14423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner usbdata.payload.data 1443fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ); 1444fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (putfunc_ret != PTP_RC_OK) 1445fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return putfunc_ret; 1446fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1447fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_NO_ZERO_READS(ptp_usb) && 1448aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner len+PTP_USB_BULK_HDR_LEN == ptp_usb->inep_maxpacket) { 1449fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1450fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("Reading in extra terminating byte\n"); 1451fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1452fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // need to read in extra byte and discard it 1453fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int result = 0, xread; 1454fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char byte = 0; 1455fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1456fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 1457fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &byte, 1458fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1, 1459fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1460fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1461fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1462fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (result != 1) 1463aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner LIBMTP_INFO("Could not read in extra byte for %d byte long file, return value 0x%04x\n", ptp_usb->inep_maxpacket, result); 1464aac75024bc25550ffdb4df95299e453842a0ababMarcus Meissner } else if (len+PTP_USB_BULK_HDR_LEN == ptp_usb->inep_maxpacket && params->split_header_data == 0) { 1465fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int zeroresult = 0, xread; 1466fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char zerobyte = 0; 1467fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1468fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("Reading in zero packet after header\n"); 1469fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1470fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij zeroresult = USB_BULK_READ(ptp_usb->handle, 1471fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->inep, 1472fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &zerobyte, 1473fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0, 1474fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1475fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1476fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1477fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (zeroresult != 0) 1478fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("LIBMTP panic: unable to read in zero packet, response 0x%04x", zeroresult); 1479fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1480fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1481fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Is that all of data? */ 1482fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (len+PTP_USB_BULK_HDR_LEN<=rlen) { 1483fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1484fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1485fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 14861165b5a73cfdad0f513867299df5c5e1a6b72c74David Bremner ret = ptp_read_func(len - (rlen - PTP_USB_BULK_HDR_LEN), 1487fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij handler, 1488fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data, &rlen, 1); 1489fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1490fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1491fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1492fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1493fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } while (0); 1494fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1495fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1496fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1497fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1498fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_getresp (PTPParams* params, PTPContainer* resp) 1499fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1500fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1501fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long rlen; 1502fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBBulkContainer usbresp; 1503fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)(params->data); 1504fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1505fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1506fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("RESPONSE: "); 1507fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1508fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(&usbresp,0,sizeof(usbresp)); 1509fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* read response, it should never be longer than sizeof(usbresp) */ 1510fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb_getpacket(params, &usbresp, &rlen); 1511fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1512fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Fix for bevahiour reported by Scott Snyder on Samsung YP-U3. The player 1513fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // sends a packet containing just zeroes of length 2 (up to 4 has been seen too) 1514fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // after a NULL packet when it should send the response. This code ignores 1515fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // such illegal packets. 1516fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij while (ret==PTP_RC_OK && rlen<PTP_USB_BULK_HDR_LEN && usbresp.length==0) { 1517fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp_usb_getresp: detected short response " 1518fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "of %d bytes, expect problems! (re-reading " 1519fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "response), rlen"); 1520fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_usb_getpacket(params, &usbresp, &rlen); 1521fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1522fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1523fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1524fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_IO; 1525fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else 1526fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbresp.type)!=PTP_USB_CONTAINER_RESPONSE) { 1527fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_ERROR_RESP_EXPECTED; 1528fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else 1529fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (dtoh16(usbresp.code)!=resp->Code) { 1530fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = dtoh16(usbresp.code); 1531fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1532fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1533fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("%04x\n", ret); 1534fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1535fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1536fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* libusb_glue_error (params, 1537fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: request code 0x%04x getting resp error 0x%04x", 1538fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Code, ret);*/ 1539fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1540fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1541fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build an appropriate PTPContainer */ 1542fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Code=dtoh16(usbresp.code); 1543fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->SessionID=params->session_id; 1544fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Transaction_ID=dtoh32(usbresp.trans_id); 1545fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_IGNORE_HEADER_ERRORS(ptp_usb)) { 1546fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (resp->Transaction_ID != params->transaction_id-1) { 1547fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_debug (params, "ptp_usb_getresp: detected a broken " 1548fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP header, transaction ID insane, expect " 1549fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "problems! (But continuing)"); 1550fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Repair the header, so it won't wreak more havoc. 1551fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Transaction_ID = params->transaction_id-1; 1552fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1553fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1554fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param1=dtoh32(usbresp.payload.params.param1); 1555fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param2=dtoh32(usbresp.payload.params.param2); 1556fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param3=dtoh32(usbresp.payload.params.param3); 1557fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param4=dtoh32(usbresp.payload.params.param4); 1558fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij resp->Param5=dtoh32(usbresp.payload.params.param5); 1559fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1560fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1561fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1562fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* Event handling functions */ 1563fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1564fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/* PTP Events wait for or check mode */ 1565fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define PTP_EVENT_CHECK 0x0000 /* waits for */ 1566fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#define PTP_EVENT_CHECK_FAST 0x0001 /* checks */ 1567fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1568fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic inline uint16_t 1569fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_event (PTPParams* params, PTPContainer* event, int wait) 1570fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1571fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret; 1572fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int result, xread; 1573fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned long rlen; 1574fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPUSBEventContainer usbevent; 157550ed219a5d4dc4bce71a0a0ebd59e8d9f9a98f9eMarcus Meissner PTP_USB *ptp_usb; 1576fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1577fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(&usbevent,0,sizeof(usbevent)); 1578fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1579fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((params==NULL) || (event==NULL)) 1580fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_BADPARAM; 158150ed219a5d4dc4bce71a0a0ebd59e8d9f9a98f9eMarcus Meissner ptp_usb = (PTP_USB *)(params->data); 158250ed219a5d4dc4bce71a0a0ebd59e8d9f9a98f9eMarcus Meissner 1583fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = PTP_RC_OK; 1584fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij switch(wait) { 1585fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case PTP_EVENT_CHECK: 15867433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1587fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1588fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1589fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1590fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1591fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0); 15927433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij if (xread == 0) 1593fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1594fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1595fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1596fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1597fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1598fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0); 1599fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (result < 0) ret = PTP_ERROR_IO; 1600fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1601fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case PTP_EVENT_CHECK_FAST: 16027433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1603fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1604fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1605fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1606fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1607fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 16087433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij if (xread == 0) 1609fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij result = USB_BULK_READ(ptp_usb->handle, 1610fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->intep, 1611fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) &usbevent, 1612fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(usbevent), 1613fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &xread, 1614fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1615fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (result < 0) ret = PTP_ERROR_IO; 1616fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1617fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij default: 16187433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij ret = PTP_ERROR_BADPARAM; 1619fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 1620fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1621fbd8e95f4ff7abfcd38a27c3c56537b8fc28203eLinus Walleij if (ret != PTP_RC_OK) { 1622fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_error (params, 1623fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: reading event an error 0x%04x occurred", ret); 1624fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1625fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 16267433938937cb07f52a5672e839f286ec1a2a7633Linus Walleij rlen = xread; 1627fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (rlen < 8) { 1628fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_glue_error (params, 1629fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "PTP: reading event an short read of %ld bytes occurred", rlen); 1630fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1631fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1632fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* if we read anything over interrupt endpoint it must be an event */ 1633fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* build an appropriate PTPContainer */ 1634fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Code=dtoh16(usbevent.code); 1635fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->SessionID=params->session_id; 1636fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Transaction_ID=dtoh32(usbevent.trans_id); 1637fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Param1=dtoh32(usbevent.param1); 1638fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Param2=dtoh32(usbevent.param2); 1639fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij event->Param3=dtoh32(usbevent.param3); 1640fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ret; 1641fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1642fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1643fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1644fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_event_check (PTPParams* params, PTPContainer* event) { 1645fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1646fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ptp_usb_event (params, event, PTP_EVENT_CHECK_FAST); 1647fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1648fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1649fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1650fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_event_wait (PTPParams* params, PTPContainer* event) { 1651fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1652fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return ptp_usb_event (params, event, PTP_EVENT_CHECK); 1653fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1654fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 16550a576519a2e7157611266a74e61b9aedf4068b69Philip Langdalestatic void 16560a576519a2e7157611266a74e61b9aedf4068b69Philip Langdaleptp_usb_event_cb (struct libusb_transfer *t) { 16570a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale struct ptp_event_cb_data *data = t->user_data; 16580a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale PTPParams *params = data->params; 16590a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale PTPUSBEventContainer *usbevent = (void *)t->buffer; 16600a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale PTPContainer event = {0,}; 16610a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale uint16_t code; 16620a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 16630a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale switch (t->status) { 16640a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale case LIBUSB_TRANSFER_COMPLETED: 16650a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale if (t->actual_length < 8) { 16660a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale libusb_glue_error (params, 16670a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale "PTP: reading event an short read of %ld bytes occurred\n", 16680a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale t->actual_length); 16690a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale code = PTP_ERROR_IO; 16700a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } else { 16710a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale event.Code=dtoh16(usbevent->code); 16720a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale event.SessionID=params->session_id; 16730a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale event.Transaction_ID=dtoh32(usbevent->trans_id); 16740a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale event.Param1=dtoh32(usbevent->param1); 16750a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale event.Param2=dtoh32(usbevent->param2); 16760a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale event.Param3=dtoh32(usbevent->param3); 16770a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale code = PTP_RC_OK; 16780a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } 16790a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale break; 16800a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale case LIBUSB_TRANSFER_TIMED_OUT: 16810a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale code = PTP_ERROR_TIMEOUT; 16820a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale break; 16830a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale case LIBUSB_TRANSFER_CANCELLED: 16840a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale code = PTP_ERROR_CANCEL; 16850a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale break; 16860a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale case LIBUSB_TRANSFER_STALL: 16870a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale code = PTP_ERROR_DATA_EXPECTED; 16880a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale break; 16890a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale case LIBUSB_TRANSFER_ERROR: 16900a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale case LIBUSB_TRANSFER_NO_DEVICE: 16910a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale case LIBUSB_TRANSFER_OVERFLOW: 16920a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale default: 16930a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale code = PTP_ERROR_IO; 16940a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale break; 16950a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } 16960a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale if (code != PTP_RC_OK) { 16970a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale libusb_glue_error (params, 16980a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale "PTP: reading event an error 0x%02x occurred\n", 16990a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale t->status); 17000a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } 17010a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale data->cb(params, code, &event, data->user_data); 17020a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale free(data); 17030a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale} 17040a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17050a576519a2e7157611266a74e61b9aedf4068b69Philip Langdaleuint16_t 17060a576519a2e7157611266a74e61b9aedf4068b69Philip Langdaleptp_usb_event_async (PTPParams* params, PTPEventCbFn cb, void *user_data) { 17070a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale PTP_USB *ptp_usb; 17080a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale PTPUSBEventContainer *usbevent; 17090a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale struct ptp_event_cb_data *data; 17100a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale struct libusb_transfer *t; 17110a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale int ret; 17120a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17130a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale if (params == NULL) { 17140a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale return PTP_ERROR_BADPARAM; 17150a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } 17160a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17170a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale usbevent = calloc(1, sizeof(*usbevent)); 17180a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale if (usbevent == NULL) { 17190a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale return PTP_ERROR_IO; 17200a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } 17210a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17220a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale data = malloc(sizeof(*data)); 17230a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale if (data == NULL) { 17240a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale free(usbevent); 17250a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale return PTP_ERROR_IO; 17260a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } 17270a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17280a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale t = libusb_alloc_transfer(0); 17290a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale if (t == NULL) { 17300a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale free(data); 17310a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale free(usbevent); 17320a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale return PTP_ERROR_IO; 17330a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale } 17340a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17350a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale data->cb = cb; 17360a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale data->user_data = user_data; 17370a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale data->params = params; 17380a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17390a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale ptp_usb = (PTP_USB *)(params->data); 17400a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale libusb_fill_interrupt_transfer(t, ptp_usb->handle, ptp_usb->intep, 17410a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale (unsigned char *)usbevent, sizeof(*usbevent), 17420a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale ptp_usb_event_cb, data, 0); 17430a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale t->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; 17440a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17450a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale ret = libusb_submit_transfer(t); 17460a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale return ret == 0 ? PTP_RC_OK : PTP_ERROR_IO; 17470a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale} 17480a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 17490a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale/** 17500a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale * Trivial wrapper around the most generic libusb method for polling for events. 17510a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale * Can be used to drive asynchronous event detection. 17520a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale */ 17530a576519a2e7157611266a74e61b9aedf4068b69Philip Langdaleint LIBMTP_Handle_Events_Timeout_Completed(struct timeval *tv, int *completed) { 17540a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale /* Pass NULL for context as libmtp always uses the default context */ 17550a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale return libusb_handle_events_timeout_completed(NULL, tv, completed); 17560a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale} 17570a576519a2e7157611266a74e61b9aedf4068b69Philip Langdale 1758fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijuint16_t 1759fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijptp_usb_control_cancel_request (PTPParams *params, uint32_t transactionid) { 1760fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb = (PTP_USB *)(params->data); 1761fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1762fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char buffer[6]; 1763fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1764fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij htod16a(&buffer[0],PTP_EC_CancelTransaction); 1765fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij htod32a(&buffer[2],transactionid); 1766fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(ptp_usb->handle, 1767fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, 1768fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0x64, 0x0000, 0x0000, 1769fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij buffer, 1770fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij sizeof(buffer), 1771fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 1772fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret < sizeof(buffer)) 1773fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_ERROR_IO; 1774fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return PTP_RC_OK; 1775fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1776fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 177715d18e31458be5006eb229df68869df2fff93495Linus Walleijstatic int init_ptp_usb(PTPParams* params, PTP_USB* ptp_usb, libusb_device* dev) 1778fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1779fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device_handle *device_handle; 1780fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij unsigned char buf[255]; 1781fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret, usbresult; 178215d18e31458be5006eb229df68869df2fff93495Linus Walleij struct libusb_config_descriptor *config; 1783fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1784fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->sendreq_func=ptp_usb_sendreq; 1785fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->senddata_func=ptp_usb_senddata; 1786fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->getresp_func=ptp_usb_getresp; 1787fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->getdata_func=ptp_usb_getdata; 1788fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->cancelreq_func=ptp_usb_control_cancel_request; 1789fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->data=ptp_usb; 1790fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->transaction_id=0; 1791fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1792fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This is hardcoded here since we have no devices whatsoever that are BE. 1793fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Change this the day we run into our first BE device (if ever). 1794fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1795fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->byteorder = PTP_DL_LE; 1796fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1797fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout = get_timeout(ptp_usb); 1798fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1799fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_open(dev, &device_handle); 1800fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 180115d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_open() failed!"); 1802fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return -1; 1803fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1804fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->handle = device_handle; 180515d18e31458be5006eb229df68869df2fff93495Linus Walleij 1806fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1807fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * If this device is known to be wrongfully claimed by other kernel 1808fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * drivers (such as mass storage), then try to unload it to make it 1809fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * accessible from user space. 1810fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1811fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_UNLOAD_DRIVER(ptp_usb) && 181215d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_kernel_driver_active(device_handle, ptp_usb->interface) 1813fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ) { 181415d18e31458be5006eb229df68869df2fff93495Linus Walleij if (LIBUSB_SUCCESS != libusb_detach_kernel_driver(device_handle, ptp_usb->interface)) { 181515d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_detach_kernel_driver() failed, continuing anyway..."); 1816fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1817fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 181815d18e31458be5006eb229df68869df2fff93495Linus Walleij 181915d18e31458be5006eb229df68869df2fff93495Linus Walleij /* 182015d18e31458be5006eb229df68869df2fff93495Linus Walleij * Check if the config is set to something else than what we want 182115d18e31458be5006eb229df68869df2fff93495Linus Walleij * to use. Only set the configuration if we absolutely have to. 182215d18e31458be5006eb229df68869df2fff93495Linus Walleij * Also do not bail out if we fail. 1823d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij * 1824d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij * Note that Darwin will not set the configuration for vendor-specific 1825d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij * devices so we need to go in and set it. 182615d18e31458be5006eb229df68869df2fff93495Linus Walleij */ 182715d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_active_config_descriptor(dev, &config); 182815d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ret != LIBUSB_SUCCESS) { 182915d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_get_active_config_descriptor(1) failed"); 1830d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij fprintf(stderr, "no active configuration, trying to set configuration\n"); 1831d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij if (libusb_set_configuration(device_handle, ptp_usb->config) != LIBUSB_SUCCESS) { 1832d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij perror("libusb_set_configuration() failed, continuing anyway..."); 1833d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij } 1834d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij ret = libusb_get_active_config_descriptor(dev, &config); 1835d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij if (ret != LIBUSB_SUCCESS) { 1836d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij perror("libusb_get_active_config_descriptor(2) failed"); 1837d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij return -1; 1838d76ae6e8ede659fd4bd13908798d3c5c86c1f1d4Linus Walleij } 1839fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 184015d18e31458be5006eb229df68869df2fff93495Linus Walleij if (config->bConfigurationValue != ptp_usb->config) { 184115d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "desired configuration different from current, trying to set configuration\n"); 184215d18e31458be5006eb229df68869df2fff93495Linus Walleij if (libusb_set_configuration(device_handle, ptp_usb->config)) { 184315d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_set_configuration() failed, continuing anyway..."); 184415d18e31458be5006eb229df68869df2fff93495Linus Walleij } 184515d18e31458be5006eb229df68869df2fff93495Linus Walleij /* Re-fetch the config descriptor if we changed */ 184615d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 184715d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_active_config_descriptor(dev, &config); 184815d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ret != LIBUSB_SUCCESS) { 184915d18e31458be5006eb229df68869df2fff93495Linus Walleij perror("libusb_get_active_config_descriptor(2) failed"); 185015d18e31458be5006eb229df68869df2fff93495Linus Walleij return -1; 185115d18e31458be5006eb229df68869df2fff93495Linus Walleij } 185215d18e31458be5006eb229df68869df2fff93495Linus Walleij } 185315d18e31458be5006eb229df68869df2fff93495Linus Walleij 185415d18e31458be5006eb229df68869df2fff93495Linus Walleij /* 185515d18e31458be5006eb229df68869df2fff93495Linus Walleij * It seems like on kernel 2.6.31 if we already have it open on another 185615d18e31458be5006eb229df68869df2fff93495Linus Walleij * pthread in our app, we'll get an error if we try to claim it again, 185715d18e31458be5006eb229df68869df2fff93495Linus Walleij * but that error is harmless because our process already claimed the interface 185815d18e31458be5006eb229df68869df2fff93495Linus Walleij */ 1859fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usbresult = libusb_claim_interface(device_handle, ptp_usb->interface); 1860fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1861fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (usbresult != 0) 186215d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "ignoring libusb_claim_interface() = %d", usbresult); 186315d18e31458be5006eb229df68869df2fff93495Linus Walleij 186415d18e31458be5006eb229df68869df2fff93495Linus Walleij /* 186515d18e31458be5006eb229df68869df2fff93495Linus Walleij * If the altsetting is set to something different than we want, switch 186615d18e31458be5006eb229df68869df2fff93495Linus Walleij * it. 186715d18e31458be5006eb229df68869df2fff93495Linus Walleij * 186815d18e31458be5006eb229df68869df2fff93495Linus Walleij * FIXME: this seems to cause trouble on the Mac:s so disable it. Retry 186915d18e31458be5006eb229df68869df2fff93495Linus Walleij * this on the Mac now that it only sets this when the altsetting differs. 187015d18e31458be5006eb229df68869df2fff93495Linus Walleij */ 1871fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#ifndef __APPLE__ 187215d18e31458be5006eb229df68869df2fff93495Linus Walleij#if 0 /* Disable this always, no idea on how to handle it */ 187315d18e31458be5006eb229df68869df2fff93495Linus Walleij if (config->interface[].altsetting[].bAlternateSetting != 187415d18e31458be5006eb229df68869df2fff93495Linus Walleij ptp_usb->altsetting) { 187515d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "desired altsetting different from current, trying to set altsetting\n"); 187615d18e31458be5006eb229df68869df2fff93495Linus Walleij usbresult = libusb_set_interface_alt_setting(device_handle, 187715d18e31458be5006eb229df68869df2fff93495Linus Walleij ptp_usb->interface, 187815d18e31458be5006eb229df68869df2fff93495Linus Walleij ptp_usb->altsetting); 187915d18e31458be5006eb229df68869df2fff93495Linus Walleij if (usbresult != 0) 188015d18e31458be5006eb229df68869df2fff93495Linus Walleij fprintf(stderr, "ignoring libusb_set_interface_alt_setting() = %d\n", usbresult); 188115d18e31458be5006eb229df68869df2fff93495Linus Walleij } 188215d18e31458be5006eb229df68869df2fff93495Linus Walleij#endif 1883fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij#endif 1884fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 188515d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 188615d18e31458be5006eb229df68869df2fff93495Linus Walleij 1887fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_SWITCH_MODE_BLACKBERRY(ptp_usb)) { 1888fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1889fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1890fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // FIXME : Only for BlackBerry Storm 1891fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // What does it mean? Maybe switch mode... 1892fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This first control message is absolutely necessary 1893fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1894fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1895fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1896fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xaa, 0x00, 0x04, buf, 0x40, 1000); 1897fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 1:\n"); 1898fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1899fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1900fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1901fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This control message is unnecessary 1902fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1903fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1904fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xa5, 0x00, 0x01, buf, 0x02, 1000); 1905fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 2:\n"); 1906fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1907fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1908fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1909fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This control message is unnecessary 1910fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1911fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1912fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xa8, 0x00, 0x01, buf, 0x05, 1000); 1913fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 3:\n"); 1914fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1915fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1916fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1917fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // This control message is unnecessary 1918fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_control_transfer(device_handle, 1919fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, 1920fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 0xa8, 0x00, 0x01, buf, 0x11, 1000); 1921fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DEBUG("BlackBerry magic part 4:\n"); 1922fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_USB_DATA(buf, ret, 16); 1923fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1924fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij usleep(1000); 1925fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1926fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return 0; 1927fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1928fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1929fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void clear_stall(PTP_USB* ptp_usb) 1930fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1931fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t status; 1932fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int ret; 1933fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1934fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* check the inep status */ 1935fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij status = 0; 1936fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = usb_get_endpoint_status(ptp_usb,ptp_usb->inep,&status); 1937fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret<0) { 1938fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror ("inep: usb_get_endpoint_status()"); 1939fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (status) { 1940fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("Clearing stall on IN endpoint\n"); 1941fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = libusb_clear_halt (ptp_usb->handle, ptp_usb->inep); 1942fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 1943fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror ("usb_clear_stall_feature()"); 1944fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1945fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1946fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1947fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* check the outep status */ 1948fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij status=0; 1949fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = usb_get_endpoint_status(ptp_usb,ptp_usb->outep,&status); 1950fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret<0) { 1951fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror("outep: usb_get_endpoint_status()"); 1952fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } else if (status) { 1953fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_INFO("Clearing stall on OUT endpoint\n"); 19541bc3a75fa2223884900136201d74905a0ad01426Linus Walleij ret = libusb_clear_halt(ptp_usb->handle, ptp_usb->outep); 1955fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) { 1956fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij perror("usb_clear_stall_feature()"); 1957fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1958fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1959fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1960fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* TODO: do we need this for INTERRUPT (ptp_usb->intep) too? */ 1961fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1962fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1963fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic void close_usb(PTP_USB* ptp_usb) 1964fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 1965fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!FLAG_NO_RELEASE_INTERFACE(ptp_usb)) { 1966fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1967fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Clear any stalled endpoints 1968fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * On misbehaving devices designed for Windows/Mac, quote from: 1969fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://www2.one-eyed-alien.net/~mdharm/linux-usb/target_offenses.txt 1970fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Device does Bad Things(tm) when it gets a GET_STATUS after CLEAR_HALT 1971fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * (...) Windows, when clearing a stall, only sends the CLEAR_HALT command, 1972fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * and presumes that the stall has cleared. Some devices actually choke 1973fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * if the CLEAR_HALT is followed by a GET_STATUS (used to determine if the 1974fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * STALL is persistant or not). 1975fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1976fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij clear_stall(ptp_usb); 1977fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_release_interface(ptp_usb->handle, (int) ptp_usb->interface); 1978fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1979fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_FORCE_RESET_ON_CLOSE(ptp_usb)) { 1980fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1981fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Some devices really love to get reset after being 1982fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * disconnected. Again, since Windows never disconnects 1983fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * a device closing behaviour is seldom or never exercised 1984fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * on devices when engineered and often error prone. 1985fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Reset may help some. 1986fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1987fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_reset_device (ptp_usb->handle); 1988fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 1989fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_close(ptp_usb->handle); 1990fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 1991fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 1992fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 1993fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Self-explanatory? 1994fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 1995fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int find_interface_and_endpoints(libusb_device *dev, 199615d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *conf, 1997fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t *interface, 199815d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t *altsetting, 1999fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep, 2000fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* inep_maxpacket, 2001fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* outep, 2002fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int *outep_maxpacket, 2003fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int* intep) 2004fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 200515d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t i, ret; 2006fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 2007fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 200815d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_device_descriptor(dev, &desc); 200915d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ret != LIBUSB_SUCCESS) 201015d18e31458be5006eb229df68869df2fff93495Linus Walleij return -1; 2011fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2012fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Loop over the device configurations 2013fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < desc.bNumConfigurations; i++) { 2014fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t j; 2015fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_config_descriptor *config; 2016fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 201715d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_config_descriptor(dev, i, &config); 201813bbf6aecb8ad3c2b0bb03dbb3500e8fe87cc08eMarcus Meissner if (ret != LIBUSB_SUCCESS) 201915d18e31458be5006eb229df68869df2fff93495Linus Walleij continue; 202015d18e31458be5006eb229df68869df2fff93495Linus Walleij 202115d18e31458be5006eb229df68869df2fff93495Linus Walleij *conf = config->bConfigurationValue; 202215d18e31458be5006eb229df68869df2fff93495Linus Walleij 2023fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Loop over each configurations interfaces 2024fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (j = 0; j < config->bNumInterfaces; j++) { 202515d18e31458be5006eb229df68869df2fff93495Linus Walleij uint8_t k, l; 2026fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint8_t no_ep; 2027fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_inep = 0; 2028fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_outep = 0; 2029fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int found_intep = 0; 2030fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij const struct libusb_endpoint_descriptor *ep; 2031fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 203215d18e31458be5006eb229df68869df2fff93495Linus Walleij // Inspect the altsettings of this interface... 203315d18e31458be5006eb229df68869df2fff93495Linus Walleij for (k = 0; k < config->interface[j].num_altsetting; k++) { 203415d18e31458be5006eb229df68869df2fff93495Linus Walleij 203515d18e31458be5006eb229df68869df2fff93495Linus Walleij // MTP devices shall have 3 endpoints, ignore those interfaces 203615d18e31458be5006eb229df68869df2fff93495Linus Walleij // that haven't. 203715d18e31458be5006eb229df68869df2fff93495Linus Walleij no_ep = config->interface[j].altsetting[k].bNumEndpoints; 203815d18e31458be5006eb229df68869df2fff93495Linus Walleij if (no_ep != 3) 203915d18e31458be5006eb229df68869df2fff93495Linus Walleij continue; 204015d18e31458be5006eb229df68869df2fff93495Linus Walleij 204115d18e31458be5006eb229df68869df2fff93495Linus Walleij *interface = config->interface[j].altsetting[k].bInterfaceNumber; 204215d18e31458be5006eb229df68869df2fff93495Linus Walleij *altsetting = config->interface[j].altsetting[k].bAlternateSetting; 204315d18e31458be5006eb229df68869df2fff93495Linus Walleij ep = config->interface[j].altsetting[k].endpoint; 204415d18e31458be5006eb229df68869df2fff93495Linus Walleij 204515d18e31458be5006eb229df68869df2fff93495Linus Walleij // Loop over the three endpoints to locate two bulk and 204615d18e31458be5006eb229df68869df2fff93495Linus Walleij // one interrupt endpoint and FAIL if we cannot, and continue. 204715d18e31458be5006eb229df68869df2fff93495Linus Walleij for (l = 0; l < no_ep; l++) { 204815d18e31458be5006eb229df68869df2fff93495Linus Walleij if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_BULK) { 204915d18e31458be5006eb229df68869df2fff93495Linus Walleij if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 205015d18e31458be5006eb229df68869df2fff93495Linus Walleij LIBUSB_ENDPOINT_DIR_MASK) { 205115d18e31458be5006eb229df68869df2fff93495Linus Walleij *inep = ep[l].bEndpointAddress; 205215d18e31458be5006eb229df68869df2fff93495Linus Walleij *inep_maxpacket = ep[l].wMaxPacketSize; 205315d18e31458be5006eb229df68869df2fff93495Linus Walleij found_inep = 1; 205415d18e31458be5006eb229df68869df2fff93495Linus Walleij } 205515d18e31458be5006eb229df68869df2fff93495Linus Walleij if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 0) { 205615d18e31458be5006eb229df68869df2fff93495Linus Walleij *outep = ep[l].bEndpointAddress; 205715d18e31458be5006eb229df68869df2fff93495Linus Walleij *outep_maxpacket = ep[l].wMaxPacketSize; 205815d18e31458be5006eb229df68869df2fff93495Linus Walleij found_outep = 1; 205915d18e31458be5006eb229df68869df2fff93495Linus Walleij } 206015d18e31458be5006eb229df68869df2fff93495Linus Walleij } else if (ep[l].bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT) { 206115d18e31458be5006eb229df68869df2fff93495Linus Walleij if ((ep[l].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == 206215d18e31458be5006eb229df68869df2fff93495Linus Walleij LIBUSB_ENDPOINT_DIR_MASK) { 206315d18e31458be5006eb229df68869df2fff93495Linus Walleij *intep = ep[l].bEndpointAddress; 206415d18e31458be5006eb229df68869df2fff93495Linus Walleij found_intep = 1; 206515d18e31458be5006eb229df68869df2fff93495Linus Walleij } 2066fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2067fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 206815d18e31458be5006eb229df68869df2fff93495Linus Walleij if (found_inep && found_outep && found_intep) { 206915d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 207015d18e31458be5006eb229df68869df2fff93495Linus Walleij // We assigned the endpoints so return here. 207115d18e31458be5006eb229df68869df2fff93495Linus Walleij return 0; 207215d18e31458be5006eb229df68869df2fff93495Linus Walleij } 207315d18e31458be5006eb229df68869df2fff93495Linus Walleij } // Next altsetting 207415d18e31458be5006eb229df68869df2fff93495Linus Walleij } // Next interface 207515d18e31458be5006eb229df68869df2fff93495Linus Walleij libusb_free_config_descriptor(config); 207615d18e31458be5006eb229df68869df2fff93495Linus Walleij } // Next config 2077fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return -1; 2078fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2079fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2080fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij/** 2081fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This function assigns params and usbinfo given a raw device 2082fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * as input. 2083fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param device the device to be assigned. 2084fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @param usbinfo a pointer to the new usbinfo. 2085fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * @return an error code. 2086fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 2087fbbef8b16876568f760986e4ff8f4921b8373fd5Linus WalleijLIBMTP_error_number_t configure_usb_device(LIBMTP_raw_device_t *device, 2088fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTPParams *params, 2089fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij void **usbinfo) 2090fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2091fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij PTP_USB *ptp_usb; 2092fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device *ldevice; 2093fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij uint16_t ret = 0; 2094fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int err, found = 0, i; 2095fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ssize_t nrofdevs; 2096fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_device **devs = NULL; 2097fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij struct libusb_device_descriptor desc; 20983df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang LIBMTP_error_number_t init_usb_ret; 2099fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2100fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* See if we can find this raw device again... */ 21013df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang init_usb_ret = init_usb(); 21023df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang if (init_usb_ret != LIBMTP_ERROR_NONE) 21033df1589b0b5b81484ebc507ac4b96d1e04891d9bLei Zhang return init_usb_ret; 2104fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 210515d18e31458be5006eb229df68869df2fff93495Linus Walleij nrofdevs = libusb_get_device_list(NULL, &devs); 2106fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij for (i = 0; i < nrofdevs ; i++) { 210715d18e31458be5006eb229df68869df2fff93495Linus Walleij if (libusb_get_bus_number(devs[i]) != device->bus_location) 2108fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 210915d18e31458be5006eb229df68869df2fff93495Linus Walleij if (libusb_get_device_address(devs[i]) != device->devnum) 2110fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij continue; 2111fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 211215d18e31458be5006eb229df68869df2fff93495Linus Walleij ret = libusb_get_device_descriptor(devs[i], &desc); 2113fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != LIBUSB_SUCCESS) continue; 2114fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2115fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(desc.idVendor == device->device_entry.vendor_id && 2116fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij desc.idProduct == device->device_entry.product_id ) { 2117fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ldevice = devs[i]; 2118fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij found = 1; 2119fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2120fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2121fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2122fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Device has gone since detecting raw devices! */ 2123fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (!found) { 2124fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_free_device_list (devs, 0); 2125fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NO_DEVICE_ATTACHED; 2126fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2127fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2128fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Allocate structs */ 2129fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb = (PTP_USB *) malloc(sizeof(PTP_USB)); 2130fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_usb == NULL) { 2131fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_free_device_list (devs, 0); 2132fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_MEMORY_ALLOCATION; 2133fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2134fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Start with a blank slate (includes setting device_flags to 0) */ 2135fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memset(ptp_usb, 0, sizeof(PTP_USB)); 2136fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2137fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy the raw device */ 2138fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij memcpy(&ptp_usb->rawdevice, device, sizeof(LIBMTP_raw_device_t)); 2139fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2140fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 2141fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * Some devices must have their "OS Descriptor" massaged in order 2142fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * to work. 2143fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 2144fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (FLAG_ALWAYS_PROBE_DESCRIPTOR(ptp_usb)) { 2145fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij // Massage the device descriptor 2146fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (void) probe_device_descriptor(ldevice, NULL); 2147fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2148fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2149fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Assign interface and endpoints to usbinfo... */ 2150fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij err = find_interface_and_endpoints(ldevice, 215115d18e31458be5006eb229df68869df2fff93495Linus Walleij &ptp_usb->config, 2152fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->interface, 215315d18e31458be5006eb229df68869df2fff93495Linus Walleij &ptp_usb->altsetting, 2154fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->inep, 2155fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->inep_maxpacket, 2156fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->outep, 2157fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->outep_maxpacket, 2158fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij &ptp_usb->intep); 2159fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2160fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (err) { 2161fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_free_device_list (devs, 0); 2162fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2163fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Unable to find interface & endpoints of device\n"); 2164fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2165fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2166fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2167fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Copy USB version number */ 2168fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->bcdusb = desc.bcdUSB; 2169fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2170fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Attempt to initialize this device */ 2171fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (init_ptp_usb(params, ptp_usb, ldevice) < 0) { 2172fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2173fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Unable to initialize device\n"); 21741e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2175fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2176fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2177fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2178fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 2179fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * This works in situations where previous bad applications 2180fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * have not used LIBMTP_Release_Device on exit 2181fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 2182fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((ret = ptp_opensession(params, 1)) == PTP_ERROR_IO) { 2183fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("PTP_ERROR_IO: failed to open session, trying again after resetting USB interface\n"); 2184fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP libusb: Attempt to reset device\n"); 2185fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_reset_device (ptp_usb->handle); 2186fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij close_usb(ptp_usb); 2187fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2188fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if(init_ptp_usb(params, ptp_usb, ldevice) <0) { 2189fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Could not init USB on second attempt\n"); 21901e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2191fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2192fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2193fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2194fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2195fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Device has been reset, try again */ 2196fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if ((ret = ptp_opensession(params, 1)) == PTP_ERROR_IO) { 2197fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: failed to open session on second attempt\n"); 21981e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2199fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2200fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2201fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2202fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2203fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2204fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Was the transaction id invalid? Try again */ 2205fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret == PTP_RC_InvalidTransactionID) { 2206fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP WARNING: Transaction ID was invalid, increment and try again\n"); 2207fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij params->transaction_id += 10; 2208fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret = ptp_opensession(params, 1); 2209fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2210fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2211fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ret != PTP_RC_SessionAlreadyOpened && ret != PTP_RC_OK) { 2212fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("LIBMTP PANIC: Could not open session! " 2213fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij "(Return code %d)\n Try to reset the device.\n", 2214fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ret); 2215fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij libusb_release_interface(ptp_usb->handle, ptp_usb->interface); 22161e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2217fe2b9d6d807c117d3ae2319db30326f1dcd5135cMarcus Meissner free (ptp_usb); 2218fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_CONNECTING; 2219fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2220fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2221fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* OK configured properly */ 2222fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *usbinfo = (void *) ptp_usb; 22231e5c80e148681f409c6d16d27336b9cd195f3387Lei Zhang libusb_free_device_list (devs, 0); 2224fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return LIBMTP_ERROR_NONE; 2225fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2226fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2227fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2228fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid close_device (PTP_USB *ptp_usb, PTPParams *params) 2229fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2230fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij if (ptp_closesession(params)!=PTP_RC_OK) 2231fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBMTP_ERROR("ERROR: Could not close session!\n"); 2232fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij close_usb(ptp_usb); 2233fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2234fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2235fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid set_usb_device_timeout(PTP_USB *ptp_usb, int timeout) 2236fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2237fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout = timeout; 2238fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2239fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2240fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijvoid get_usb_device_timeout(PTP_USB *ptp_usb, int *timeout) 2241fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2242fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij *timeout = ptp_usb->timeout; 2243fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2244fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2245fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijint guess_usb_speed(PTP_USB *ptp_usb) 2246fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2247fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij int bytes_per_second; 2248fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2249fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 2250fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * We don't know the actual speeds so these are rough guesses 2251fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * from the info you can find here: 2252fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://en.wikipedia.org/wiki/USB#Transfer_rates 2253fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij * http://www.barefeats.com/usb2.html 2254fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij */ 2255fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij switch (ptp_usb->bcdusb & 0xFF00) { 2256fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case 0x0100: 2257fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* 1.x USB versions let's say 1MiB/s */ 2258fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_per_second = 1*1024*1024; 2259fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2260fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case 0x0200: 2261fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij case 0x0300: 2262fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* USB 2.0 nominal speed 18MiB/s */ 2263fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* USB 3.0 won't be worse? */ 2264fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_per_second = 18*1024*1024; 2265fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2266fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij default: 2267fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij /* Half-guess something? */ 2268fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij bytes_per_second = 1*1024*1024; 2269fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij break; 2270fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij } 2271fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return bytes_per_second; 2272fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2273fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2274fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleijstatic int usb_get_endpoint_status(PTP_USB* ptp_usb, int ep, uint16_t* status) 2275fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij{ 2276fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij return libusb_control_transfer(ptp_usb->handle, 2277fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_ENDPOINT, 2278fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij LIBUSB_REQUEST_GET_STATUS, 2279fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij USB_FEATURE_HALT, 2280fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ep, 2281fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij (unsigned char *) status, 2282fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij 2, 2283fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij ptp_usb->timeout); 2284fbbef8b16876568f760986e4ff8f4921b8373fd5Linus Walleij} 2285