blob: d67758732b3152535272161b13f621d9a74d8b9a [file] [log] [blame]
rjw2e8229f2022-02-15 21:08:12 +08001/*
2 * Copyright (C) 2007 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 <string.h>
20
21#include <sysdeps.h>
22#include "transport_pcie.h"
23
24#define TRACE_TAG TRACE_TRANSPORT
25#include "adb.h"
26
27#ifdef HAVE_BIG_ENDIAN
28#define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24)
29static inline void fix_endians(apacket *p)
30{
31 p->msg.command = H4(p->msg.command);
32 p->msg.arg0 = H4(p->msg.arg0);
33 p->msg.arg1 = H4(p->msg.arg1);
34 p->msg.data_length = H4(p->msg.data_length);
35 p->msg.data_check = H4(p->msg.data_check);
36 p->msg.magic = H4(p->msg.magic);
37}
38unsigned host_to_le32(unsigned n)
39{
40 return H4(n);
41}
42#else
43#define fix_endians(p) do {} while (0)
44unsigned host_to_le32(unsigned n)
45{
46 return n;
47}
48#endif
49
50static int remote_read(apacket *p, atransport *t)
51{
52 struct pcie_handle *pcie = t->pcie;
53
54 if(unix_read(pcie->fd, &p->msg, sizeof(amessage)) < 0){
55 D("remote pcie: read terminated (message)\n");
56 return -1;
57 }
58
59 fix_endians(p);
60
61 if(check_header(p)) {
62 D("remote pcie: check_header failed\n");
63 return -1;
64 }
65
66 if(p->msg.data_length) {
67 if(unix_read(pcie->fd, p->data, p->msg.data_length) < 0){
68 D("remote pcie: terminated (data)\n");
69 return -1;
70 }
71 }
72
73 if(check_data(p)) {
74 D("remote pcie: check_data failed\n");
75 return -1;
76 }
77
78 return 0;
79}
80
81static int remote_write(apacket *p, atransport *t)
82{
83 unsigned size = p->msg.data_length;
84 struct pcie_handle *pcie = t->pcie;
85
86 fix_endians(p);
87
88 if(unix_write(pcie->fd, &p->msg, sizeof(amessage)) < 0) {
89 D("remote pcie: 1 - write terminated\n");
90 return -1;
91 }
92
93 if(p->msg.data_length == 0)
94 return 0;
95
96 if(unix_write(pcie->fd, p->data, size) < 0) {
97 D("remote pcie: 2 - write terminated\n");
98 return -1;
99 }
100
101 return 0;
102}
103
104static void remote_close(atransport *t)
105{
106 struct pcie_handle *pcie = t->pcie;
107
108 unix_close(pcie->fd);
109 pcie->fd = -1;
110}
111
112static void remote_kick(atransport *t)
113{
114 struct pcie_handle *pcie = t->pcie;
115
116 if (pcie->kick)
117 pcie->kick(pcie);
118}
119
120void init_pcie_transport(atransport *t, struct pcie_handle *h, const char *devpath, int state)
121{
122 static char *pcie_unknow = "0123456mediatek";
123 D("transport: pcie\n");
124 /* On host side, we need open the file here */
125 if (h->fd < 0)
126 h->fd = unix_open(devpath, O_RDWR);
127
128 t->close = remote_close;
129 t->kick = remote_kick;
130 t->read_from_remote = remote_read;
131 t->write_to_remote = remote_write;
132 t->sync_token = 1;
133 t->connection_state = state;
134 t->type = kTransportUsb;
135 t->pcie = h;
136
137 /* Device information */
138 t->serial = pcie_unknow;
139 t->device = pcie_unknow;
140 t->product = pcie_unknow;
141
142#if ADB_HOST
143 HOST = 1;
144#else
145 HOST = 0;
146#endif
147}
148
149#if ADB_HOST
150void pcie_host_init(void)
151{
152 struct pcie_handle *pcie;
153
154 pcie = calloc(1, sizeof(*pcie));
155
156 pcie->fd = unix_open(PCIE_ADB_PATH, O_RDWR);
157
158 register_pcie_transport(pcie, PCIE_ADB_PATH, 1);
159}
160
161#else
162/* For ADBD */
163static void *pcie_open_thread(void *x)
164{
165 struct pcie_handle *pcie = (struct pcie_handle *)x;
166 int fd = -1;
167 char *banner = "Start PCIe port\n";
168
169 while (1) {
170 adb_mutex_lock(&pcie->lock);
171 while (pcie->fd != -1)
172 adb_cond_wait(&pcie->notify, &pcie->lock);
173 adb_mutex_unlock(&pcie->lock);
174
175 do {
176 fd = unix_open(PCIE_ADB_PATH, O_RDWR);
177 if (fd < 0) {
178 adb_sleep_ms(1000);
179 }
180 } while (fd < 0);
181
182 pcie->fd = fd;
183 adb_write(fd, banner, strlen(banner));
184
185 /* Get PCIe config information */
186 fd = unix_open(PCIE_INFO_ADB_PATH, O_RDONLY);
187 if (fd > 0) {
188 pcie->info = calloc(1, sizeof(struct pcie_info));
189 if (pcie->info)
190 unix_read(fd, pcie->info, sizeof(pcie->info));
191
192 unix_close(fd);
193 }
194
195 register_pcie_transport(pcie, PCIE_ADB_PATH, 1);
196 }
197
198 // never gets here
199 return 0;
200}
201
202static void pcie_adbd_kick(struct pcie_handle *h)
203{
204 adb_mutex_lock(&h->lock);
205 unix_close(h->fd);
206 h->fd = -1;
207
208 adb_cond_signal(&h->notify);
209 adb_mutex_unlock(&h->lock);
210}
211
212void pcie_init(void)
213{
214 adb_thread_t tid;
215 struct pcie_handle *h;
216
217 h = calloc(1, sizeof(*h));
218
219 h->kick = pcie_adbd_kick;
220 h->fd = -1;
221
222 adb_cond_init(&h->notify, 0);
223 adb_mutex_init(&h->lock, 0);
224
225 D("[ pcie_init - starting thread ]\n");
226 if (adb_thread_create(&tid, pcie_open_thread, h)) {
227 fatal_errno("[ cannot create pcie thread ]\n");
228 }
229}
230#endif