libnfc  1.4.2
pn53x_usb.c
Go to the documentation of this file.
1 /*-
2  * Public platform independent Near Field Communication (NFC) library
3  *
4  * Copyright (C) 2009, Roel Verdult
5  * Copyright (C) 2010, Romain Tartière, Romuald Conty
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>
19  */
20 
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif // HAVE_CONFIG_H
29 
30 /*
31 Thanks to d18c7db and Okko for example code
32 */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <usb.h>
37 #include <string.h>
38 
39 #include "../drivers.h"
40 #include "../chips/pn53x.h"
41 
42 #include <nfc/nfc.h>
43 #include <nfc/nfc-messages.h>
44 
45 #define BUFFER_LENGTH 256
46 #define USB_TIMEOUT 0
47 
48 // TODO Move this HACK1 into an upper level in order to benefit to other devices that use PN53x
49 static const byte_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
50 
51 void pn53x_usb_ack (nfc_device_t * pnd);
52 
53 // Find transfer endpoints for bulk transfers
54 void
55 get_end_points (struct usb_device *dev, usb_spec_t * pus)
56 {
57  uint32_t uiIndex;
58  uint32_t uiEndPoint;
59  struct usb_interface_descriptor *puid = dev->config->interface->altsetting;
60 
61  // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
62  for (uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) {
63  // Only accept bulk transfer endpoints (ignore interrupt endpoints)
64  if (puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK)
65  continue;
66 
67  // Copy the endpoint to a local var, makes it more readable code
68  uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress;
69 
70  // Test if we dealing with a bulk IN endpoint
71  if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) {
72  pus->uiEndPointIn = uiEndPoint;
73  pus->wMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
74  }
75  // Test if we dealing with a bulk OUT endpoint
76  if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) {
77  pus->uiEndPointOut = uiEndPoint;
78  pus->wMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
79  }
80  }
81 }
82 
83 bool
84 pn53x_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound,
85  usb_candidate_t candidates[], int num_candidates, char *target_name)
86 {
87  int ret,
88  i;
89 
90  struct usb_bus *bus;
91  struct usb_device *dev;
92  usb_dev_handle *udev;
93  uint32_t uiBusIndex = 0;
94  char string[256];
95 
96  string[0] = '\0';
97  usb_init ();
98 
99  // usb_find_busses will find all of the busses on the system. Returns the number of changes since previous call to this function (total of new busses and busses removed).
100  if ((ret = usb_find_busses () < 0))
101  return false;
102  // usb_find_devices will find all of the devices on each bus. This should be called after usb_find_busses. Returns the number of changes since the previous call to this function (total of new device and devices removed).
103  if ((ret = usb_find_devices () < 0))
104  return false;
105 
106  *pszDeviceFound = 0;
107 
108  for (bus = usb_get_busses (); bus; bus = bus->next) {
109  for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++) {
110  for (i = 0; i < num_candidates; ++i) {
111  // DBG("Checking device %04x:%04x (%04x:%04x)",dev->descriptor.idVendor,dev->descriptor.idProduct,candidates[i].idVendor,candidates[i].idProduct);
112  if (candidates[i].idVendor == dev->descriptor.idVendor && candidates[i].idProduct == dev->descriptor.idProduct) {
113  // Make sure there are 2 endpoints available
114  // with libusb-win32 we got some null pointers so be robust before looking at endpoints:
115  if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) {
116  // Nope, we maybe want the next one, let's try to find another
117  continue;
118  }
119  if (dev->config->interface->altsetting->bNumEndpoints < 2) {
120  // Nope, we maybe want the next one, let's try to find another
121  continue;
122  }
123  if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) {
124  udev = usb_open (dev);
125  if (udev) {
126  usb_get_string_simple (udev, dev->descriptor.iManufacturer, string, sizeof (string));
127  if (strlen (string) > 0)
128  strcpy (string + strlen (string), " / ");
129  usb_get_string_simple (udev, dev->descriptor.iProduct, string + strlen (string),
130  sizeof (string) - strlen (string));
131  }
132  usb_close (udev);
133  }
134  if (strlen (string) == 0)
135  strcpy (pnddDevices[*pszDeviceFound].acDevice, target_name);
136  else
137  strcpy (pnddDevices[*pszDeviceFound].acDevice, string);
138  pnddDevices[*pszDeviceFound].pcDriver = target_name;
139  pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
140  (*pszDeviceFound)++;
141  // Test if we reach the maximum "wanted" devices
142  if ((*pszDeviceFound) == szDevices) {
143  return true;
144  }
145  }
146  }
147  }
148  }
149  if (*pszDeviceFound)
150  return true;
151  return false;
152 }
153 
154 nfc_device_t *
155 pn53x_usb_connect (const nfc_device_desc_t * pndd, const char *target_name, int target_chip)
156 {
157  nfc_device_t *pnd = NULL;
158  usb_spec_t *pus;
159  usb_spec_t us;
160  struct usb_bus *bus;
161  struct usb_device *dev;
162  uint32_t uiBusIndex;
163 
164  us.uiEndPointIn = 0;
165  us.uiEndPointOut = 0;
166  us.pudh = NULL;
167 
168  DBG ("Attempt to connect to %s device", target_name);
169  usb_init ();
170 
171  uiBusIndex = pndd->uiBusIndex;
172 
173  for (bus = usb_get_busses (); bus; bus = bus->next) {
174  for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--) {
175  DBG ("Checking device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
176  if (uiBusIndex == 0) {
177  // Open the USB device
178  us.pudh = usb_open (dev);
179 
180  get_end_points (dev, &us);
181  if (usb_set_configuration (us.pudh, 1) < 0) {
182  ERR ("Unable to set USB configuration, please check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
183  usb_close (us.pudh);
184  // we failed to use the specified device
185  return NULL;
186  }
187 
188  if (usb_claim_interface (us.pudh, 0) < 0) {
189  DBG ("%s", "Can't claim interface");
190  usb_close (us.pudh);
191  // we failed to use the specified device
192  return NULL;
193  }
194  // Copy VendorId and ProductId
195  us.uc.idVendor = dev->descriptor.idVendor;
196  us.uc.idProduct = dev->descriptor.idProduct;
197  // Allocate memory for the device info and specification, fill it and return the info
198  pus = malloc (sizeof (usb_spec_t));
199  *pus = us;
200  pnd = malloc (sizeof (nfc_device_t));
201  strcpy (pnd->acName, target_name);
202  pnd->nc = target_chip;
203  pnd->nds = (nfc_device_spec_t) pus;
204  pnd->bActive = true;
205 
206  // HACK1: Send first an ACK as Abort command, to reset chip before talking to it:
207  pn53x_usb_ack (pnd);
208 
209  // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device
210  // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do
211  byte_t abtTx[] = { 0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a, 0x00 };
212  byte_t abtRx[BUFFER_LENGTH];
213  int ret;
214 #ifdef DEBUG
215  PRINT_HEX ("TX", abtTx, sizeof(abtTx));
216 #endif
217  ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, sizeof(abtTx), USB_TIMEOUT);
218  if (ret < 0) {
219  DBG ("usb_bulk_write failed with error %d", ret);
220  usb_close (us.pudh);
221  // we failed to use the specified device
222  return NULL;
223  }
224  ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
225  if (ret < 0) {
226  DBG ("usb_bulk_read failed with error %d", ret);
227  usb_close (us.pudh);
228  // we failed to use the specified device
229  return NULL;
230  }
231 #ifdef DEBUG
232  PRINT_HEX ("RX", abtRx, ret);
233 #endif
234  if (ret == 6) { // we got the ACK/NACK properly
235  if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret)) {
236  DBG ("usb_bulk_read failed getting ACK");
237  usb_close (us.pudh);
238  // we failed to use the specified device
239  return NULL;
240  }
241  ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
242  if (ret < 0) {
243  DBG ("usb_bulk_read failed with error %d", ret);
244  usb_close (us.pudh);
245  // we failed to use the specified device
246  return NULL;
247  }
248 #ifdef DEBUG
249  PRINT_HEX ("RX", abtRx, ret);
250 #endif
251  }
252 
253  return pnd;
254  }
255  }
256  }
257  // We ran out of devices before the index required
258  DBG ("%s", "Device index not found!");
259  return NULL;
260 }
261 
262 void
263 pn53x_usb_disconnect (nfc_device_t * pnd)
264 {
265  usb_spec_t *pus = (usb_spec_t *) pnd->nds;
266  int ret;
267 
268  pn53x_usb_ack (pnd);
269 
270  if ((ret = usb_release_interface (pus->pudh, 0)) < 0) {
271  ERR ("usb_release_interface failed (%i)", ret);
272  }
273 
274  if ((ret = usb_close (pus->pudh)) < 0) {
275  ERR ("usb_close failed (%i)", ret);
276  }
277 /*
278  if((ret = usb_reset(pus->pudh)) < 0) {
279  ERR("usb_reset failed (%i, if errno: %s)",ret, strerror(-ret));
280  }
281 */
282  free (pnd->nds);
283  free (pnd);
284 }
285 
286 bool
287 pn53x_usb_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx)
288 {
289  size_t uiPos = 0;
290  int ret = 0;
291  byte_t abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
292  byte_t abtRx[BUFFER_LENGTH];
293  usb_spec_t *pus = (usb_spec_t *) pnd->nds;
294  // TODO: Move this one level up for libnfc-1.6
295  uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
296 
297  // Packet length = data length (len) + checksum (1) + end of stream marker (1)
298  abtTx[3] = szTx;
299  // Packet length checksum
300  abtTx[4] = 0x0100 - abtTx[3];
301  // Copy the PN53X command into the packet abtTx
302  memmove (abtTx + 5, pbtTx, szTx);
303 
304  // Calculate data payload checksum
305  abtTx[szTx + 5] = 0;
306  for (uiPos = 0; uiPos < szTx; uiPos++) {
307  abtTx[szTx + 5] -= abtTx[uiPos + 5];
308  }
309 
310  // End of stream marker
311  abtTx[szTx + 6] = 0;
312 
313 #ifdef DEBUG
314  PRINT_HEX ("TX", abtTx, szTx + 7);
315 #endif
316 
317  ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, szTx + 7, USB_TIMEOUT);
318  // HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details
319  if ((ret % pus->wMaxPacketSize) == 0) {
320  usb_bulk_write (pus->pudh, pus->uiEndPointOut, "\0", 0, USB_TIMEOUT);
321  }
322 
323  if (ret < 0) {
324  DBG ("usb_bulk_write failed with error %d", ret);
325  pnd->iLastError = DEIO;
326  return false;
327  }
328 
329  ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
330  if (ret < 0) {
331  DBG ("usb_bulk_read failed with error %d", ret);
332  pnd->iLastError = DEIO;
333  // try to interrupt current device state
334  pn53x_usb_ack(pnd);
335  return false;
336  }
337 #ifdef DEBUG
338  PRINT_HEX ("RX", abtRx, ret);
339 #endif
340 
341  if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret))
342  return false;
343 
344  ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
345  if (ret < 0) {
346  DBG ("usb_bulk_read failed with error %d", ret);
347  pnd->iLastError = DEIO;
348  // try to interrupt current device state
349  pn53x_usb_ack(pnd);
350  return false;
351  }
352 #ifdef DEBUG
353  PRINT_HEX ("RX", abtRx, ret);
354 #endif
355 
356 #ifdef DEBUG
357  PRINT_HEX ("TX", ack_frame, 6);
358 #endif
359  usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, 6, USB_TIMEOUT);
360 
361  if (!pn53x_check_error_frame_callback (pnd, abtRx, ret))
362  return false;
363 
364  // When the answer should be ignored, just return a succesful result
365  if (pbtRx == NULL || pszRx == NULL)
366  return true;
367 
368  // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
369  if (ret < 9) {
370  DBG ("%s", "No data");
371  pnd->iLastError = DEINVAL;
372  return false;
373  }
374  // Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
375  *pszRx = ret - 7 - 2;
376 
377  memcpy (pbtRx, abtRx + 7, *pszRx);
378 
379  return true;
380 }
381 
382 void
383 pn53x_usb_ack (nfc_device_t * pnd)
384 {
385  usb_spec_t *pus = (usb_spec_t *) pnd->nds;
386 #ifdef DEBUG
387  PRINT_HEX ("TX", ack_frame, sizeof (ack_frame));
388 #endif
389  usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, sizeof (ack_frame), USB_TIMEOUT);
390 }