MtpDevice.cpp revision 755fd617258d3f1731b2829d681cab680db0fdd5
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/types.h>
20#include <sys/ioctl.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <errno.h>
24
25#include <usbhost/usbhost.h>
26
27#include "MtpDevice.h"
28#include "MtpDebug.h"
29#include "MtpDeviceInfo.h"
30#include "MtpObjectInfo.h"
31#include "MtpStorageInfo.h"
32#include "MtpStringBuffer.h"
33
34namespace android {
35
36MtpDevice::MtpDevice(struct usb_device* device, int interface,
37            struct usb_endpoint *ep_in, struct usb_endpoint *ep_out,
38            struct usb_endpoint *ep_intr)
39    :   mDevice(device),
40        mInterface(interface),
41        mEndpointIn(ep_in),
42        mEndpointOut(ep_out),
43        mEndpointIntr(ep_intr),
44        mDeviceInfo(NULL),
45        mID(usb_device_get_unique_id(device)),
46        mSessionID(0),
47        mTransactionID(0)
48{
49}
50
51MtpDevice::~MtpDevice() {
52    close();
53}
54
55void MtpDevice::initialize() {
56    openSession();
57    mDeviceInfo = getDeviceInfo();
58    if (mDeviceInfo) {
59        mDeviceInfo->print();
60    }
61}
62
63void MtpDevice::close() {
64    if (mDevice) {
65        usb_device_release_interface(mDevice, mInterface);
66        usb_device_close(mDevice);
67        mDevice = NULL;
68    }
69}
70
71const char* MtpDevice::getDeviceName() {
72    if (mDevice)
73        return usb_device_get_name(mDevice);
74    else
75        return "???";
76}
77
78bool MtpDevice::openSession() {
79printf("openSession\n");
80    mSessionID = 0;
81    mTransactionID = 0;
82    MtpSessionID newSession = 1;
83    mRequest.reset();
84    mRequest.setParameter(1, newSession);
85    if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
86        return false;
87    MtpResponseCode ret = readResponse();
88    if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
89        newSession = mResponse.getParameter(1);
90    else if (ret != MTP_RESPONSE_OK)
91        return false;
92
93    mSessionID = newSession;
94    mTransactionID = 1;
95    return true;
96}
97
98bool MtpDevice::closeSession() {
99    // FIXME
100    return true;
101}
102
103MtpDeviceInfo* MtpDevice::getDeviceInfo() {
104    mRequest.reset();
105    if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
106        return NULL;
107    if (!readData())
108        return NULL;
109    MtpResponseCode ret = readResponse();
110printf("getDeviceInfo returned %04X\n", ret);
111    if (ret == MTP_RESPONSE_OK) {
112        MtpDeviceInfo* info = new MtpDeviceInfo;
113        info->read(mData);
114        return info;
115    }
116    return NULL;
117}
118
119MtpStorageIDList* MtpDevice::getStorageIDs() {
120    mRequest.reset();
121    if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
122        return NULL;
123    if (!readData())
124        return NULL;
125    MtpResponseCode ret = readResponse();
126    if (ret == MTP_RESPONSE_OK) {
127        return mData.getAUInt32();
128    }
129    return NULL;
130}
131
132MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
133    mRequest.reset();
134    mRequest.setParameter(1, storageID);
135    if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
136        return NULL;
137    if (!readData())
138        return NULL;
139    MtpResponseCode ret = readResponse();
140printf("getStorageInfo returned %04X\n", ret);
141    if (ret == MTP_RESPONSE_OK) {
142        MtpStorageInfo* info = new MtpStorageInfo(storageID);
143        info->read(mData);
144        return info;
145    }
146    return NULL;
147}
148
149MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
150            MtpObjectFormat format, MtpObjectHandle parent) {
151    mRequest.reset();
152    mRequest.setParameter(1, storageID);
153    mRequest.setParameter(2, format);
154    mRequest.setParameter(3, parent);
155    if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
156        return NULL;
157    if (!readData())
158        return NULL;
159    MtpResponseCode ret = readResponse();
160printf("getObjectHandles returned %04X\n", ret);
161    if (ret == MTP_RESPONSE_OK) {
162        return mData.getAUInt32();
163    }
164    return NULL;
165}
166
167MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
168    mRequest.reset();
169    mRequest.setParameter(1, handle);
170    if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
171        return NULL;
172    if (!readData())
173        return NULL;
174    MtpResponseCode ret = readResponse();
175printf("getObjectInfo returned %04X\n", ret);
176    if (ret == MTP_RESPONSE_OK) {
177        MtpObjectInfo* info = new MtpObjectInfo(handle);
178        info->read(mData);
179        return info;
180    }
181    return NULL;
182}
183
184bool MtpDevice::sendRequest(MtpOperationCode operation) {
185    printf("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
186    mRequest.setOperationCode(operation);
187    if (mTransactionID > 0)
188        mRequest.setTransactionID(mTransactionID++);
189    int ret = mRequest.write(mEndpointOut);
190    mRequest.dump();
191    return (ret > 0);
192}
193
194bool MtpDevice::sendData(MtpOperationCode operation) {
195    printf("sendData\n");
196    mData.setOperationCode(mRequest.getOperationCode());
197    mData.setTransactionID(mRequest.getTransactionID());
198    int ret = mData.write(mEndpointOut);
199    mData.dump();
200    return (ret > 0);
201}
202
203bool MtpDevice::readData() {
204    mData.reset();
205    int ret = mData.read(mEndpointIn);
206    printf("readData returned %d\n", ret);
207    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
208        mData.dump();
209        return true;
210    }
211    else {
212        printf("readResponse failed\n");
213        return false;
214    }
215}
216
217MtpResponseCode MtpDevice::readResponse() {
218    printf("readResponse\n");
219    int ret = mResponse.read(mEndpointIn);
220    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
221        mResponse.dump();
222        return mResponse.getResponseCode();
223    }
224    else {
225        printf("readResponse failed\n");
226        return -1;
227    }
228}
229
230}  // namespace android
231