xref: /aosp_15_r20/frameworks/av/media/mtp/MtpPacket.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MtpPacket"
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker #include "MtpDebug.h"
20*ec779b8eSAndroid Build Coastguard Worker #include "MtpPacket.h"
21*ec779b8eSAndroid Build Coastguard Worker #include "mtp.h"
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include <stdio.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <stdlib.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <stdio.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker #include <usbhost/usbhost.h>
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker namespace android {
30*ec779b8eSAndroid Build Coastguard Worker 
MtpPacket(int bufferSize)31*ec779b8eSAndroid Build Coastguard Worker MtpPacket::MtpPacket(int bufferSize)
32*ec779b8eSAndroid Build Coastguard Worker     :   mBuffer(NULL),
33*ec779b8eSAndroid Build Coastguard Worker         mBufferSize(bufferSize),
34*ec779b8eSAndroid Build Coastguard Worker         mAllocationIncrement(bufferSize),
35*ec779b8eSAndroid Build Coastguard Worker         mPacketSize(0)
36*ec779b8eSAndroid Build Coastguard Worker {
37*ec779b8eSAndroid Build Coastguard Worker     mBuffer = (uint8_t *)malloc(bufferSize);
38*ec779b8eSAndroid Build Coastguard Worker     if (!mBuffer) {
39*ec779b8eSAndroid Build Coastguard Worker         ALOGE("out of memory!");
40*ec779b8eSAndroid Build Coastguard Worker         abort();
41*ec779b8eSAndroid Build Coastguard Worker     }
42*ec779b8eSAndroid Build Coastguard Worker }
43*ec779b8eSAndroid Build Coastguard Worker 
~MtpPacket()44*ec779b8eSAndroid Build Coastguard Worker MtpPacket::~MtpPacket() {
45*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer)
46*ec779b8eSAndroid Build Coastguard Worker         free(mBuffer);
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker 
reset()49*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::reset() {
50*ec779b8eSAndroid Build Coastguard Worker     allocate(MTP_CONTAINER_HEADER_SIZE);
51*ec779b8eSAndroid Build Coastguard Worker     mPacketSize = MTP_CONTAINER_HEADER_SIZE;
52*ec779b8eSAndroid Build Coastguard Worker     memset(mBuffer, 0, mBufferSize);
53*ec779b8eSAndroid Build Coastguard Worker }
54*ec779b8eSAndroid Build Coastguard Worker 
allocate(size_t length)55*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::allocate(size_t length) {
56*ec779b8eSAndroid Build Coastguard Worker     if (length > mBufferSize) {
57*ec779b8eSAndroid Build Coastguard Worker         int newLength = length + mAllocationIncrement;
58*ec779b8eSAndroid Build Coastguard Worker         mBuffer = (uint8_t *)realloc(mBuffer, newLength);
59*ec779b8eSAndroid Build Coastguard Worker         if (!mBuffer) {
60*ec779b8eSAndroid Build Coastguard Worker             ALOGE("out of memory!");
61*ec779b8eSAndroid Build Coastguard Worker             abort();
62*ec779b8eSAndroid Build Coastguard Worker         }
63*ec779b8eSAndroid Build Coastguard Worker         mBufferSize = newLength;
64*ec779b8eSAndroid Build Coastguard Worker     }
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker 
dump()67*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::dump() {
68*ec779b8eSAndroid Build Coastguard Worker #define DUMP_BYTES_PER_ROW  16
69*ec779b8eSAndroid Build Coastguard Worker     char buffer[500];
70*ec779b8eSAndroid Build Coastguard Worker     char* bufptr = buffer;
71*ec779b8eSAndroid Build Coastguard Worker 
72*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < mPacketSize; i++) {
73*ec779b8eSAndroid Build Coastguard Worker         bufptr += snprintf(bufptr, sizeof(buffer) - (bufptr - buffer), "%02X ",
74*ec779b8eSAndroid Build Coastguard Worker                            mBuffer[i]);
75*ec779b8eSAndroid Build Coastguard Worker         if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
76*ec779b8eSAndroid Build Coastguard Worker             ALOGV("%s", buffer);
77*ec779b8eSAndroid Build Coastguard Worker             bufptr = buffer;
78*ec779b8eSAndroid Build Coastguard Worker         }
79*ec779b8eSAndroid Build Coastguard Worker     }
80*ec779b8eSAndroid Build Coastguard Worker     if (bufptr != buffer) {
81*ec779b8eSAndroid Build Coastguard Worker         // print last line
82*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s", buffer);
83*ec779b8eSAndroid Build Coastguard Worker     }
84*ec779b8eSAndroid Build Coastguard Worker     ALOGV("\n");
85*ec779b8eSAndroid Build Coastguard Worker }
86*ec779b8eSAndroid Build Coastguard Worker 
copyFrom(const MtpPacket & src)87*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::copyFrom(const MtpPacket& src) {
88*ec779b8eSAndroid Build Coastguard Worker     int length = src.mPacketSize;
89*ec779b8eSAndroid Build Coastguard Worker     allocate(length);
90*ec779b8eSAndroid Build Coastguard Worker     mPacketSize = length;
91*ec779b8eSAndroid Build Coastguard Worker     memcpy(mBuffer, src.mBuffer, length);
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker 
getUInt16(int offset) const94*ec779b8eSAndroid Build Coastguard Worker uint16_t MtpPacket::getUInt16(int offset) const {
95*ec779b8eSAndroid Build Coastguard Worker     if ((unsigned long)(offset+2) <= mBufferSize) {
96*ec779b8eSAndroid Build Coastguard Worker         return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
97*ec779b8eSAndroid Build Coastguard Worker     }
98*ec779b8eSAndroid Build Coastguard Worker     else {
99*ec779b8eSAndroid Build Coastguard Worker         ALOGE("offset for buffer read is greater than buffer size!");
100*ec779b8eSAndroid Build Coastguard Worker         return 0;
101*ec779b8eSAndroid Build Coastguard Worker     }
102*ec779b8eSAndroid Build Coastguard Worker }
103*ec779b8eSAndroid Build Coastguard Worker 
getUInt32(int offset) const104*ec779b8eSAndroid Build Coastguard Worker uint32_t MtpPacket::getUInt32(int offset) const {
105*ec779b8eSAndroid Build Coastguard Worker     if ((unsigned long)(offset+4) <= mBufferSize) {
106*ec779b8eSAndroid Build Coastguard Worker         return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
107*ec779b8eSAndroid Build Coastguard Worker                ((uint32_t)mBuffer[offset + 1] << 8)  | (uint32_t)mBuffer[offset];
108*ec779b8eSAndroid Build Coastguard Worker     }
109*ec779b8eSAndroid Build Coastguard Worker     else {
110*ec779b8eSAndroid Build Coastguard Worker         ALOGE("offset for buffer read is greater than buffer size!");
111*ec779b8eSAndroid Build Coastguard Worker         return 0;
112*ec779b8eSAndroid Build Coastguard Worker     }
113*ec779b8eSAndroid Build Coastguard Worker }
114*ec779b8eSAndroid Build Coastguard Worker 
putUInt16(int offset,uint16_t value)115*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::putUInt16(int offset, uint16_t value) {
116*ec779b8eSAndroid Build Coastguard Worker     if ((unsigned long)(offset+2) <= mBufferSize) {
117*ec779b8eSAndroid Build Coastguard Worker         mBuffer[offset++] = (uint8_t)(value & 0xFF);
118*ec779b8eSAndroid Build Coastguard Worker         mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
119*ec779b8eSAndroid Build Coastguard Worker     }
120*ec779b8eSAndroid Build Coastguard Worker     else {
121*ec779b8eSAndroid Build Coastguard Worker         ALOGE("offset for buffer write is greater than buffer size!");
122*ec779b8eSAndroid Build Coastguard Worker     }
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker 
putUInt32(int offset,uint32_t value)125*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::putUInt32(int offset, uint32_t value) {
126*ec779b8eSAndroid Build Coastguard Worker     if ((unsigned long)(offset+4) <= mBufferSize) {
127*ec779b8eSAndroid Build Coastguard Worker         mBuffer[offset++] = (uint8_t)(value & 0xFF);
128*ec779b8eSAndroid Build Coastguard Worker         mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
129*ec779b8eSAndroid Build Coastguard Worker         mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
130*ec779b8eSAndroid Build Coastguard Worker         mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
131*ec779b8eSAndroid Build Coastguard Worker     }
132*ec779b8eSAndroid Build Coastguard Worker     else {
133*ec779b8eSAndroid Build Coastguard Worker         ALOGE("offset for buffer write is greater than buffer size!");
134*ec779b8eSAndroid Build Coastguard Worker     }
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker 
getContainerCode() const137*ec779b8eSAndroid Build Coastguard Worker uint16_t MtpPacket::getContainerCode() const {
138*ec779b8eSAndroid Build Coastguard Worker     return getUInt16(MTP_CONTAINER_CODE_OFFSET);
139*ec779b8eSAndroid Build Coastguard Worker }
140*ec779b8eSAndroid Build Coastguard Worker 
setContainerCode(uint16_t code)141*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::setContainerCode(uint16_t code) {
142*ec779b8eSAndroid Build Coastguard Worker     putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
143*ec779b8eSAndroid Build Coastguard Worker }
144*ec779b8eSAndroid Build Coastguard Worker 
getContainerType() const145*ec779b8eSAndroid Build Coastguard Worker uint16_t MtpPacket::getContainerType() const {
146*ec779b8eSAndroid Build Coastguard Worker     return getUInt16(MTP_CONTAINER_TYPE_OFFSET);
147*ec779b8eSAndroid Build Coastguard Worker }
148*ec779b8eSAndroid Build Coastguard Worker 
getTransactionID() const149*ec779b8eSAndroid Build Coastguard Worker MtpTransactionID MtpPacket::getTransactionID() const {
150*ec779b8eSAndroid Build Coastguard Worker     return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET);
151*ec779b8eSAndroid Build Coastguard Worker }
152*ec779b8eSAndroid Build Coastguard Worker 
setTransactionID(MtpTransactionID id)153*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::setTransactionID(MtpTransactionID id) {
154*ec779b8eSAndroid Build Coastguard Worker     putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
155*ec779b8eSAndroid Build Coastguard Worker }
156*ec779b8eSAndroid Build Coastguard Worker 
getParameter(int index) const157*ec779b8eSAndroid Build Coastguard Worker uint32_t MtpPacket::getParameter(int index) const {
158*ec779b8eSAndroid Build Coastguard Worker     if (index < 1 || index > 5) {
159*ec779b8eSAndroid Build Coastguard Worker         ALOGE("index %d out of range in MtpPacket::getParameter", index);
160*ec779b8eSAndroid Build Coastguard Worker         return 0;
161*ec779b8eSAndroid Build Coastguard Worker     }
162*ec779b8eSAndroid Build Coastguard Worker     return getUInt32(MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t));
163*ec779b8eSAndroid Build Coastguard Worker }
164*ec779b8eSAndroid Build Coastguard Worker 
setParameter(int index,uint32_t value)165*ec779b8eSAndroid Build Coastguard Worker void MtpPacket::setParameter(int index, uint32_t value) {
166*ec779b8eSAndroid Build Coastguard Worker     if (index < 1 || index > 5) {
167*ec779b8eSAndroid Build Coastguard Worker         ALOGE("index %d out of range in MtpPacket::setParameter", index);
168*ec779b8eSAndroid Build Coastguard Worker         return;
169*ec779b8eSAndroid Build Coastguard Worker     }
170*ec779b8eSAndroid Build Coastguard Worker     int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t);
171*ec779b8eSAndroid Build Coastguard Worker     if (mPacketSize < offset + sizeof(uint32_t)) {
172*ec779b8eSAndroid Build Coastguard Worker         mPacketSize = offset + sizeof(uint32_t);
173*ec779b8eSAndroid Build Coastguard Worker         allocate(mPacketSize);
174*ec779b8eSAndroid Build Coastguard Worker     }
175*ec779b8eSAndroid Build Coastguard Worker     putUInt32(offset, value);
176*ec779b8eSAndroid Build Coastguard Worker }
177*ec779b8eSAndroid Build Coastguard Worker 
178*ec779b8eSAndroid Build Coastguard Worker #ifdef MTP_HOST
transfer(struct usb_request * request)179*ec779b8eSAndroid Build Coastguard Worker int MtpPacket::transfer(struct usb_request* request) {
180*ec779b8eSAndroid Build Coastguard Worker     if (request->dev == NULL) {
181*ec779b8eSAndroid Build Coastguard Worker         return -1;
182*ec779b8eSAndroid Build Coastguard Worker     }
183*ec779b8eSAndroid Build Coastguard Worker     int result = usb_device_bulk_transfer(request->dev,
184*ec779b8eSAndroid Build Coastguard Worker                             request->endpoint,
185*ec779b8eSAndroid Build Coastguard Worker                             request->buffer,
186*ec779b8eSAndroid Build Coastguard Worker                             request->buffer_length,
187*ec779b8eSAndroid Build Coastguard Worker                             5000);
188*ec779b8eSAndroid Build Coastguard Worker     request->actual_length = result;
189*ec779b8eSAndroid Build Coastguard Worker     return result;
190*ec779b8eSAndroid Build Coastguard Worker }
191*ec779b8eSAndroid Build Coastguard Worker #endif
192*ec779b8eSAndroid Build Coastguard Worker 
193*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
194