usb_moded  0.86.0+mer57
usb_moded-android.c
Go to the documentation of this file.
1 
25 #include "usb_moded-android.h"
26 
28 #include "usb_moded-log.h"
29 #include "usb_moded-mac.h"
30 #include "usb_moded-modesetting.h"
31 
32 #include <unistd.h>
33 #include <stdio.h>
34 
35 /* ========================================================================= *
36  * Prototypes
37  * ========================================================================= */
38 
39 /* ------------------------------------------------------------------------- *
40  * ANDROID
41  * ------------------------------------------------------------------------- */
42 
43 static bool android_write_file (const char *path, const char *text);
44 bool android_in_use (void);
45 static bool android_probe (void);
46 gchar *android_get_serial (void);
47 bool android_init (void);
48 void android_quit (void);
49 bool android_set_enabled (bool enable);
50 bool android_set_charging_mode(void);
51 bool android_set_function (const char *function);
52 bool android_set_productid (const char *id);
53 bool android_set_vendorid (const char *id);
54 bool android_set_attr (const char *function, const char *attr, const char *value);
55 
56 /* ========================================================================= *
57  * Data
58  * ========================================================================= */
59 
60 static int android_probed = -1;
61 
62 /* ========================================================================= *
63  * Functions
64  * ========================================================================= */
65 
66 static bool
67 android_write_file(const char *path, const char *text)
68 {
69  LOG_REGISTER_CONTEXT;
70 
71  bool ack = false;
72 
73  if( !path || !text )
74  goto EXIT;
75 
76  log_debug("WRITE %s '%s'", path, text);
77 
78  char buff[64];
79  snprintf(buff, sizeof buff, "%s\n", text);
80 
81  if( write_to_file(path, buff) == -1 )
82  goto EXIT;
83 
84  ack = true;
85 
86 EXIT:
87 
88  return ack;
89 }
90 
91 bool
92 android_in_use(void)
93 {
94  LOG_REGISTER_CONTEXT;
95 
96  if( android_probed < 0 )
97  log_debug("android_in_use() called before android_probe()");
98 
99  return android_probed > 0;
100 }
101 
102 static bool
103 android_probe(void)
104 {
105  LOG_REGISTER_CONTEXT;
106 
107  if( android_probed <= 0 ) {
108  android_probed = access(ANDROID0_ENABLE, F_OK) == 0;
109  log_warning("ANDROID0 %sdetected", android_probed ? "" : "not ");
110  }
111 
112  return android_in_use();
113 }
114 
117 gchar *
119 {
120  LOG_REGISTER_CONTEXT;
121 
122  static const char path[] = "/proc/cmdline";
123  static const char find[] = "androidboot.serialno=";
124  static const char pbrk[] = " \t\r\n,";
125 
126  char *res = 0;
127  FILE *file = 0;
128  size_t size = 0;
129  char *data = 0;
130 
131  if( !(file = fopen(path, "r")) ) {
132  log_warning("%s: %s: %m", path, "can't open");
133  goto EXIT;
134  }
135 
136  if( getline(&data, &size, file) < 0 ) {
137  log_warning("%s: %s: %m", path, "can't read");
138  goto EXIT;
139  }
140 
141  char *beg = strstr(data, find);
142  if( !beg ) {
143  log_warning("%s: no serial found", path);
144  goto EXIT;
145  }
146 
147  beg += sizeof find - 1;
148  size_t len = strcspn(beg, pbrk);
149  if( len < 1 ) {
150  log_warning("%s: empty serial found", path);
151  goto EXIT;
152  }
153 
154  res = g_strndup(beg, len);
155 
156 EXIT:
157 
158  free(data);
159 
160  if( file )
161  fclose(file);
162 
163  return res;
164 }
165 
170 bool
172 {
173  LOG_REGISTER_CONTEXT;
174 
175  gchar *text;
176 
177  if( !android_probe() )
178  goto EXIT;
179 
180  /* Disable */
181  android_set_enabled(false);
182 
183  /* Configure */
184  if( (text = android_get_serial()) )
185  {
186  android_write_file(ANDROID0_SERIAL, text);
187  g_free(text);
188  }
189 
190  text = config_get_android_manufacturer();
191  if(text)
192  {
193  android_write_file(ANDROID0_MANUFACTURER, text);
194  g_free(text);
195  }
196  text = config_get_android_vendor_id();
197  if(text)
198  {
199  android_set_vendorid(text);
200  g_free(text);
201  }
202  text = config_get_android_product();
203  if(text)
204  {
205  android_write_file(ANDROID0_PRODUCT, text);
206  g_free(text);
207  }
208  text = config_get_android_product_id();
209  if(text)
210  {
211  android_set_productid(text);
212  g_free(text);
213  }
214  text = mac_read_mac();
215  if(text)
216  {
217  android_set_attr("f_rndis", "ethaddr", text);
218  g_free(text);
219  }
220  /* For rndis to be discovered correctly in M$ Windows (vista and later) */
221  android_set_attr("f_rndis", "wceis", "1");
222 
223  /* Make sure remnants off mass-storage mode do not cause
224  * issues for charging_fallback & co */
225  android_set_attr("f_mass_storage", "lun/nofua", "0");
226  android_set_attr("f_mass_storage", "lun/file", "");
227 
228 EXIT:
229  return android_in_use();
230 }
231 
234 void
236 {
237  /* For now this exists for symmetry with other backends only */
238 }
239 
240 bool
241 android_set_enabled(bool enable)
242 {
243  LOG_REGISTER_CONTEXT;
244 
245  bool ack = false;
246  if( android_in_use() ) {
247  const char *val = enable ? "1" : "0";
248  ack = android_write_file(ANDROID0_ENABLE, val);
249  }
250  log_debug("ANDROID %s(%d) -> %d", __func__, enable, ack);
251  return ack;
252 }
253 
254 /* Set a charging mode for the android gadget
255  *
256  * @return true if successful, false on failure
257  */
258 bool
259 android_set_charging_mode(void)
260 {
261  LOG_REGISTER_CONTEXT;
262 
263  bool ack = false;
264 
265  if( !android_in_use() )
266  goto EXIT;
267 
268  if( !android_set_function("mass_storage") )
269  goto EXIT;
270 
271  /* TODO: make configurable */
272  if( !android_set_productid("0AFE") )
273  goto EXIT;
274 
275  if( !android_set_enabled(true) )
276  goto EXIT;
277 
278  ack = true;
279 
280 EXIT:
281  log_debug("ANDROID %s() -> %d", __func__, ack);
282  return ack;
283 }
284 
285 /* Set a function for the android gadget
286  *
287  * @return true if successful, false on failure
288  */
289 bool
290 android_set_function(const char *function)
291 {
292  LOG_REGISTER_CONTEXT;
293 
294  bool ack = false;
295 
296  if( !function )
297  goto EXIT;
298 
299  if( !android_in_use() )
300  goto EXIT;
301 
302  if( !android_set_enabled(false) )
303  goto EXIT;
304 
305  if( !android_write_file(ANDROID0_FUNCTIONS, function) )
306  goto EXIT;
307 
308  /* Leave disabled, so that caller can adjust attributes
309  * etc before enabling */
310 
311  ack = true;
312 EXIT:
313 
314  log_debug("ANDROID %s(%s) -> %d", __func__, function, ack);
315  return ack;
316 }
317 
318 /* Set a product id for the android gadget
319  *
320  * @return true if successful, false on failure
321  */
322 bool
323 android_set_productid(const char *id)
324 {
325  LOG_REGISTER_CONTEXT;
326 
327  bool ack = false;
328 
329  if( id && android_in_use() ) {
330  char str[16];
331  char *end = 0;
332  unsigned num = strtol(id, &end, 16);
333  if( end > id && *end == 0 ) {
334  snprintf(str, sizeof str, "%04x", num);
335  id = str;
336  }
337  ack = android_write_file(ANDROID0_ID_PRODUCT, id);
338  }
339  log_debug("ANDROID %s(%s) -> %d", __func__, id, ack);
340  return ack;
341 }
342 
343 /* Set a vendor id for the android gadget
344  *
345  * @return true if successful, false on failure
346  */
347 bool
348 android_set_vendorid(const char *id)
349 {
350  LOG_REGISTER_CONTEXT;
351 
352  bool ack = false;
353  if( id && android_in_use() ) {
354  char str[16];
355  char *end = 0;
356  unsigned num = strtol(id, &end, 16);
357  if( end > id && *end == 0 ) {
358  snprintf(str, sizeof str, "%04x", num);
359  id = str;
360  }
361  ack = android_write_file(ANDROID0_ID_VENDOR, id);
362  }
363  log_debug("ANDROID %s(%s) -> %d", __func__, id, ack);
364  return ack;
365 }
366 
371 bool
372 android_set_attr(const char *function, const char *attr, const char *value)
373 {
374  LOG_REGISTER_CONTEXT;
375 
376  bool ack = false;
377 
378  if( function && attr && value && android_in_use() ) {
379  char path[256];
380  snprintf(path, sizeof path, "%s/%s/%s",
381  ANDROID0_DIRECTORY, function, attr);
382  ack = android_write_file(path, value);
383  }
384  log_debug("ANDROID %s(%s, %s, %s) -> %d", __func__,
385  function, attr, value, ack);
386  return ack;
387 }
android_get_serial
gchar * android_get_serial(void)
Definition: usb_moded-android.c:118
usb_moded-modesetting.h
usb_moded-mac.h
usb_moded-android.h
usb_moded-config-private.h
android_set_attr
bool android_set_attr(const char *function, const char *attr, const char *value)
Definition: usb_moded-android.c:372
usb_moded-log.h
android_init
bool android_init(void)
Definition: usb_moded-android.c:171
android_quit
void android_quit(void)
Definition: usb_moded-android.c:235