libnfc
1.4.2
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library 00003 * 00004 * Copyright (C) 2009, Roel Verdult 00005 * Copyright (C) 2010, Romain Tartière, Romuald Conty 00006 * 00007 * This program is free software: you can redistribute it and/or modify it 00008 * under the terms of the GNU Lesser General Public License as published by the 00009 * Free Software Foundation, either version 3 of the License, or (at your 00010 * option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, but WITHOUT 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00015 * more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public License 00018 * along with this program. If not, see <http://www.gnu.org/licenses/> 00019 */ 00020 00026 #ifdef HAVE_CONFIG_H 00027 # include "config.h" 00028 #endif // HAVE_CONFIG_H 00029 00030 /* 00031 Thanks to d18c7db and Okko for example code 00032 */ 00033 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <usb.h> 00037 #include <string.h> 00038 00039 #include "../drivers.h" 00040 #include "../chips/pn53x.h" 00041 00042 #include <nfc/nfc.h> 00043 #include <nfc/nfc-messages.h> 00044 00045 #define BUFFER_LENGTH 256 00046 #define USB_TIMEOUT 0 00047 00048 // TODO Move this HACK1 into an upper level in order to benefit to other devices that use PN53x 00049 static const byte_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; 00050 00051 void pn53x_usb_ack (nfc_device_t * pnd); 00052 00053 // Find transfer endpoints for bulk transfers 00054 void 00055 get_end_points (struct usb_device *dev, usb_spec_t * pus) 00056 { 00057 uint32_t uiIndex; 00058 uint32_t uiEndPoint; 00059 struct usb_interface_descriptor *puid = dev->config->interface->altsetting; 00060 00061 // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out 00062 for (uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) { 00063 // Only accept bulk transfer endpoints (ignore interrupt endpoints) 00064 if (puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK) 00065 continue; 00066 00067 // Copy the endpoint to a local var, makes it more readable code 00068 uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress; 00069 00070 // Test if we dealing with a bulk IN endpoint 00071 if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) { 00072 pus->uiEndPointIn = uiEndPoint; 00073 pus->wMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize; 00074 } 00075 // Test if we dealing with a bulk OUT endpoint 00076 if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) { 00077 pus->uiEndPointOut = uiEndPoint; 00078 pus->wMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize; 00079 } 00080 } 00081 } 00082 00083 bool 00084 pn53x_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound, 00085 usb_candidate_t candidates[], int num_candidates, char *target_name) 00086 { 00087 int ret, 00088 i; 00089 00090 struct usb_bus *bus; 00091 struct usb_device *dev; 00092 usb_dev_handle *udev; 00093 uint32_t uiBusIndex = 0; 00094 char string[256]; 00095 00096 string[0] = '\0'; 00097 usb_init (); 00098 00099 // 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). 00100 if ((ret = usb_find_busses () < 0)) 00101 return false; 00102 // 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). 00103 if ((ret = usb_find_devices () < 0)) 00104 return false; 00105 00106 *pszDeviceFound = 0; 00107 00108 for (bus = usb_get_busses (); bus; bus = bus->next) { 00109 for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++) { 00110 for (i = 0; i < num_candidates; ++i) { 00111 // DBG("Checking device %04x:%04x (%04x:%04x)",dev->descriptor.idVendor,dev->descriptor.idProduct,candidates[i].idVendor,candidates[i].idProduct); 00112 if (candidates[i].idVendor == dev->descriptor.idVendor && candidates[i].idProduct == dev->descriptor.idProduct) { 00113 // Make sure there are 2 endpoints available 00114 // with libusb-win32 we got some null pointers so be robust before looking at endpoints: 00115 if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { 00116 // Nope, we maybe want the next one, let's try to find another 00117 continue; 00118 } 00119 if (dev->config->interface->altsetting->bNumEndpoints < 2) { 00120 // Nope, we maybe want the next one, let's try to find another 00121 continue; 00122 } 00123 if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) { 00124 udev = usb_open (dev); 00125 if (udev) { 00126 usb_get_string_simple (udev, dev->descriptor.iManufacturer, string, sizeof (string)); 00127 if (strlen (string) > 0) 00128 strcpy (string + strlen (string), " / "); 00129 usb_get_string_simple (udev, dev->descriptor.iProduct, string + strlen (string), 00130 sizeof (string) - strlen (string)); 00131 } 00132 usb_close (udev); 00133 } 00134 if (strlen (string) == 0) 00135 strcpy (pnddDevices[*pszDeviceFound].acDevice, target_name); 00136 else 00137 strcpy (pnddDevices[*pszDeviceFound].acDevice, string); 00138 pnddDevices[*pszDeviceFound].pcDriver = target_name; 00139 pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex; 00140 (*pszDeviceFound)++; 00141 // Test if we reach the maximum "wanted" devices 00142 if ((*pszDeviceFound) == szDevices) { 00143 return true; 00144 } 00145 } 00146 } 00147 } 00148 } 00149 if (*pszDeviceFound) 00150 return true; 00151 return false; 00152 } 00153 00154 nfc_device_t * 00155 pn53x_usb_connect (const nfc_device_desc_t * pndd, const char *target_name, int target_chip) 00156 { 00157 nfc_device_t *pnd = NULL; 00158 usb_spec_t *pus; 00159 usb_spec_t us; 00160 struct usb_bus *bus; 00161 struct usb_device *dev; 00162 uint32_t uiBusIndex; 00163 00164 us.uiEndPointIn = 0; 00165 us.uiEndPointOut = 0; 00166 us.pudh = NULL; 00167 00168 DBG ("Attempt to connect to %s device", target_name); 00169 usb_init (); 00170 00171 uiBusIndex = pndd->uiBusIndex; 00172 00173 for (bus = usb_get_busses (); bus; bus = bus->next) { 00174 for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--) { 00175 DBG ("Checking device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct); 00176 if (uiBusIndex == 0) { 00177 // Open the USB device 00178 us.pudh = usb_open (dev); 00179 00180 get_end_points (dev, &us); 00181 if (usb_set_configuration (us.pudh, 1) < 0) { 00182 ERR ("Unable to set USB configuration, please check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct); 00183 usb_close (us.pudh); 00184 // we failed to use the specified device 00185 return NULL; 00186 } 00187 00188 if (usb_claim_interface (us.pudh, 0) < 0) { 00189 DBG ("%s", "Can't claim interface"); 00190 usb_close (us.pudh); 00191 // we failed to use the specified device 00192 return NULL; 00193 } 00194 // Copy VendorId and ProductId 00195 us.uc.idVendor = dev->descriptor.idVendor; 00196 us.uc.idProduct = dev->descriptor.idProduct; 00197 // Allocate memory for the device info and specification, fill it and return the info 00198 pus = malloc (sizeof (usb_spec_t)); 00199 *pus = us; 00200 pnd = malloc (sizeof (nfc_device_t)); 00201 strcpy (pnd->acName, target_name); 00202 pnd->nc = target_chip; 00203 pnd->nds = (nfc_device_spec_t) pus; 00204 pnd->bActive = true; 00205 00206 // HACK1: Send first an ACK as Abort command, to reset chip before talking to it: 00207 pn53x_usb_ack (pnd); 00208 00209 // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device 00210 // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do 00211 byte_t abtTx[] = { 0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a, 0x00 }; 00212 byte_t abtRx[BUFFER_LENGTH]; 00213 int ret; 00214 #ifdef DEBUG 00215 PRINT_HEX ("TX", abtTx, sizeof(abtTx)); 00216 #endif 00217 ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, sizeof(abtTx), USB_TIMEOUT); 00218 if (ret < 0) { 00219 DBG ("usb_bulk_write failed with error %d", ret); 00220 usb_close (us.pudh); 00221 // we failed to use the specified device 00222 return NULL; 00223 } 00224 ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT); 00225 if (ret < 0) { 00226 DBG ("usb_bulk_read failed with error %d", ret); 00227 usb_close (us.pudh); 00228 // we failed to use the specified device 00229 return NULL; 00230 } 00231 #ifdef DEBUG 00232 PRINT_HEX ("RX", abtRx, ret); 00233 #endif 00234 if (ret == 6) { // we got the ACK/NACK properly 00235 if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret)) { 00236 DBG ("usb_bulk_read failed getting ACK"); 00237 usb_close (us.pudh); 00238 // we failed to use the specified device 00239 return NULL; 00240 } 00241 ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT); 00242 if (ret < 0) { 00243 DBG ("usb_bulk_read failed with error %d", ret); 00244 usb_close (us.pudh); 00245 // we failed to use the specified device 00246 return NULL; 00247 } 00248 #ifdef DEBUG 00249 PRINT_HEX ("RX", abtRx, ret); 00250 #endif 00251 } 00252 00253 return pnd; 00254 } 00255 } 00256 } 00257 // We ran out of devices before the index required 00258 DBG ("%s", "Device index not found!"); 00259 return NULL; 00260 } 00261 00262 void 00263 pn53x_usb_disconnect (nfc_device_t * pnd) 00264 { 00265 usb_spec_t *pus = (usb_spec_t *) pnd->nds; 00266 int ret; 00267 00268 pn53x_usb_ack (pnd); 00269 00270 if ((ret = usb_release_interface (pus->pudh, 0)) < 0) { 00271 ERR ("usb_release_interface failed (%i)", ret); 00272 } 00273 00274 if ((ret = usb_close (pus->pudh)) < 0) { 00275 ERR ("usb_close failed (%i)", ret); 00276 } 00277 /* 00278 if((ret = usb_reset(pus->pudh)) < 0) { 00279 ERR("usb_reset failed (%i, if errno: %s)",ret, strerror(-ret)); 00280 } 00281 */ 00282 free (pnd->nds); 00283 free (pnd); 00284 } 00285 00286 bool 00287 pn53x_usb_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx) 00288 { 00289 size_t uiPos = 0; 00290 int ret = 0; 00291 byte_t abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" 00292 byte_t abtRx[BUFFER_LENGTH]; 00293 usb_spec_t *pus = (usb_spec_t *) pnd->nds; 00294 // TODO: Move this one level up for libnfc-1.6 00295 uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; 00296 00297 // Packet length = data length (len) + checksum (1) + end of stream marker (1) 00298 abtTx[3] = szTx; 00299 // Packet length checksum 00300 abtTx[4] = 0x0100 - abtTx[3]; 00301 // Copy the PN53X command into the packet abtTx 00302 memmove (abtTx + 5, pbtTx, szTx); 00303 00304 // Calculate data payload checksum 00305 abtTx[szTx + 5] = 0; 00306 for (uiPos = 0; uiPos < szTx; uiPos++) { 00307 abtTx[szTx + 5] -= abtTx[uiPos + 5]; 00308 } 00309 00310 // End of stream marker 00311 abtTx[szTx + 6] = 0; 00312 00313 #ifdef DEBUG 00314 PRINT_HEX ("TX", abtTx, szTx + 7); 00315 #endif 00316 00317 ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, szTx + 7, USB_TIMEOUT); 00318 // HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details 00319 if ((ret % pus->wMaxPacketSize) == 0) { 00320 usb_bulk_write (pus->pudh, pus->uiEndPointOut, "\0", 0, USB_TIMEOUT); 00321 } 00322 00323 if (ret < 0) { 00324 DBG ("usb_bulk_write failed with error %d", ret); 00325 pnd->iLastError = DEIO; 00326 return false; 00327 } 00328 00329 ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT); 00330 if (ret < 0) { 00331 DBG ("usb_bulk_read failed with error %d", ret); 00332 pnd->iLastError = DEIO; 00333 // try to interrupt current device state 00334 pn53x_usb_ack(pnd); 00335 return false; 00336 } 00337 #ifdef DEBUG 00338 PRINT_HEX ("RX", abtRx, ret); 00339 #endif 00340 00341 if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret)) 00342 return false; 00343 00344 ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT); 00345 if (ret < 0) { 00346 DBG ("usb_bulk_read failed with error %d", ret); 00347 pnd->iLastError = DEIO; 00348 // try to interrupt current device state 00349 pn53x_usb_ack(pnd); 00350 return false; 00351 } 00352 #ifdef DEBUG 00353 PRINT_HEX ("RX", abtRx, ret); 00354 #endif 00355 00356 #ifdef DEBUG 00357 PRINT_HEX ("TX", ack_frame, 6); 00358 #endif 00359 usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, 6, USB_TIMEOUT); 00360 00361 if (!pn53x_check_error_frame_callback (pnd, abtRx, ret)) 00362 return false; 00363 00364 // When the answer should be ignored, just return a succesful result 00365 if (pbtRx == NULL || pszRx == NULL) 00366 return true; 00367 00368 // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) 00369 if (ret < 9) { 00370 DBG ("%s", "No data"); 00371 pnd->iLastError = DEINVAL; 00372 return false; 00373 } 00374 // Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable) 00375 *pszRx = ret - 7 - 2; 00376 00377 memcpy (pbtRx, abtRx + 7, *pszRx); 00378 00379 return true; 00380 } 00381 00382 void 00383 pn53x_usb_ack (nfc_device_t * pnd) 00384 { 00385 usb_spec_t *pus = (usb_spec_t *) pnd->nds; 00386 #ifdef DEBUG 00387 PRINT_HEX ("TX", ack_frame, sizeof (ack_frame)); 00388 #endif 00389 usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, sizeof (ack_frame), USB_TIMEOUT); 00390 }