]>
Commit | Line | Data |
---|---|---|
1ccea77e | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
9815c7cf MT |
2 | /* |
3 | * Driver for NXP PN533 NFC Chip - USB transport layer | |
4 | * | |
5 | * Copyright (C) 2011 Instituto Nokia de Tecnologia | |
6 | * Copyright (C) 2012-2013 Tieto Poland | |
9815c7cf MT |
7 | */ |
8 | ||
9 | #include <linux/device.h> | |
10 | #include <linux/kernel.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/slab.h> | |
13 | #include <linux/usb.h> | |
14 | #include <linux/nfc.h> | |
15 | #include <linux/netdevice.h> | |
16 | #include <net/nfc/nfc.h> | |
17 | #include "pn533.h" | |
18 | ||
19 | #define VERSION "0.1" | |
20 | ||
21 | #define PN533_VENDOR_ID 0x4CC | |
22 | #define PN533_PRODUCT_ID 0x2533 | |
23 | ||
24 | #define SCM_VENDOR_ID 0x4E6 | |
25 | #define SCL3711_PRODUCT_ID 0x5591 | |
26 | ||
27 | #define SONY_VENDOR_ID 0x054c | |
28 | #define PASORI_PRODUCT_ID 0x02e1 | |
29 | ||
30 | #define ACS_VENDOR_ID 0x072f | |
31 | #define ACR122U_PRODUCT_ID 0x2200 | |
32 | ||
33 | static const struct usb_device_id pn533_usb_table[] = { | |
34 | { USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID), | |
35 | .driver_info = PN533_DEVICE_STD }, | |
36 | { USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID), | |
37 | .driver_info = PN533_DEVICE_STD }, | |
38 | { USB_DEVICE(SONY_VENDOR_ID, PASORI_PRODUCT_ID), | |
39 | .driver_info = PN533_DEVICE_PASORI }, | |
40 | { USB_DEVICE(ACS_VENDOR_ID, ACR122U_PRODUCT_ID), | |
41 | .driver_info = PN533_DEVICE_ACR122U }, | |
42 | { } | |
43 | }; | |
44 | MODULE_DEVICE_TABLE(usb, pn533_usb_table); | |
45 | ||
46 | struct pn533_usb_phy { | |
47 | struct usb_device *udev; | |
48 | struct usb_interface *interface; | |
49 | ||
50 | struct urb *out_urb; | |
51 | struct urb *in_urb; | |
52 | ||
dbafc289 GKH |
53 | struct urb *ack_urb; |
54 | u8 *ack_buffer; | |
55 | ||
9815c7cf MT |
56 | struct pn533 *priv; |
57 | }; | |
58 | ||
59 | static void pn533_recv_response(struct urb *urb) | |
60 | { | |
61 | struct pn533_usb_phy *phy = urb->context; | |
62 | struct sk_buff *skb = NULL; | |
63 | ||
64 | if (!urb->status) { | |
ecc443c0 | 65 | skb = alloc_skb(urb->actual_length, GFP_ATOMIC); |
9815c7cf MT |
66 | if (!skb) { |
67 | nfc_err(&phy->udev->dev, "failed to alloc memory\n"); | |
68 | } else { | |
59ae1d12 JB |
69 | skb_put_data(skb, urb->transfer_buffer, |
70 | urb->actual_length); | |
9815c7cf MT |
71 | } |
72 | } | |
73 | ||
74 | pn533_recv_frame(phy->priv, skb, urb->status); | |
75 | } | |
76 | ||
77 | static int pn533_submit_urb_for_response(struct pn533_usb_phy *phy, gfp_t flags) | |
78 | { | |
79 | phy->in_urb->complete = pn533_recv_response; | |
80 | ||
81 | return usb_submit_urb(phy->in_urb, flags); | |
82 | } | |
83 | ||
84 | static void pn533_recv_ack(struct urb *urb) | |
85 | { | |
86 | struct pn533_usb_phy *phy = urb->context; | |
87 | struct pn533 *priv = phy->priv; | |
88 | struct pn533_cmd *cmd = priv->cmd; | |
89 | struct pn533_std_frame *in_frame; | |
90 | int rc; | |
91 | ||
92 | cmd->status = urb->status; | |
93 | ||
94 | switch (urb->status) { | |
95 | case 0: | |
96 | break; /* success */ | |
97 | case -ECONNRESET: | |
98 | case -ENOENT: | |
99 | dev_dbg(&phy->udev->dev, | |
100 | "The urb has been stopped (status %d)\n", | |
101 | urb->status); | |
102 | goto sched_wq; | |
103 | case -ESHUTDOWN: | |
104 | default: | |
105 | nfc_err(&phy->udev->dev, | |
106 | "Urb failure (status %d)\n", urb->status); | |
107 | goto sched_wq; | |
108 | } | |
109 | ||
110 | in_frame = phy->in_urb->transfer_buffer; | |
111 | ||
112 | if (!pn533_rx_frame_is_ack(in_frame)) { | |
113 | nfc_err(&phy->udev->dev, "Received an invalid ack\n"); | |
114 | cmd->status = -EIO; | |
115 | goto sched_wq; | |
116 | } | |
117 | ||
118 | rc = pn533_submit_urb_for_response(phy, GFP_ATOMIC); | |
119 | if (rc) { | |
120 | nfc_err(&phy->udev->dev, | |
121 | "usb_submit_urb failed with result %d\n", rc); | |
122 | cmd->status = rc; | |
123 | goto sched_wq; | |
124 | } | |
125 | ||
126 | return; | |
127 | ||
128 | sched_wq: | |
129 | queue_work(priv->wq, &priv->cmd_complete_work); | |
130 | } | |
131 | ||
132 | static int pn533_submit_urb_for_ack(struct pn533_usb_phy *phy, gfp_t flags) | |
133 | { | |
134 | phy->in_urb->complete = pn533_recv_ack; | |
135 | ||
136 | return usb_submit_urb(phy->in_urb, flags); | |
137 | } | |
138 | ||
139 | static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags) | |
140 | { | |
141 | struct pn533_usb_phy *phy = dev->phy; | |
8b55d758 | 142 | static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; |
9815c7cf | 143 | /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ |
9815c7cf | 144 | |
dbafc289 GKH |
145 | if (!phy->ack_buffer) { |
146 | phy->ack_buffer = kmemdup(ack, sizeof(ack), flags); | |
147 | if (!phy->ack_buffer) | |
148 | return -ENOMEM; | |
149 | } | |
9815c7cf | 150 | |
dbafc289 GKH |
151 | phy->ack_urb->transfer_buffer = phy->ack_buffer; |
152 | phy->ack_urb->transfer_buffer_length = sizeof(ack); | |
153 | return usb_submit_urb(phy->ack_urb, flags); | |
9815c7cf MT |
154 | } |
155 | ||
156 | static int pn533_usb_send_frame(struct pn533 *dev, | |
157 | struct sk_buff *out) | |
158 | { | |
159 | struct pn533_usb_phy *phy = dev->phy; | |
160 | int rc; | |
161 | ||
162 | if (phy->priv == NULL) | |
163 | phy->priv = dev; | |
164 | ||
165 | phy->out_urb->transfer_buffer = out->data; | |
166 | phy->out_urb->transfer_buffer_length = out->len; | |
167 | ||
168 | print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1, | |
169 | out->data, out->len, false); | |
170 | ||
171 | rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); | |
172 | if (rc) | |
173 | return rc; | |
174 | ||
175 | if (dev->protocol_type == PN533_PROTO_REQ_RESP) { | |
176 | /* request for response for sent packet directly */ | |
ecc443c0 | 177 | rc = pn533_submit_urb_for_response(phy, GFP_KERNEL); |
9815c7cf MT |
178 | if (rc) |
179 | goto error; | |
180 | } else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) { | |
181 | /* request for ACK if that's the case */ | |
182 | rc = pn533_submit_urb_for_ack(phy, GFP_KERNEL); | |
183 | if (rc) | |
184 | goto error; | |
185 | } | |
186 | ||
187 | return 0; | |
188 | ||
189 | error: | |
190 | usb_unlink_urb(phy->out_urb); | |
191 | return rc; | |
192 | } | |
193 | ||
194 | static void pn533_usb_abort_cmd(struct pn533 *dev, gfp_t flags) | |
195 | { | |
196 | struct pn533_usb_phy *phy = dev->phy; | |
197 | ||
198 | /* ACR122U does not support any command which aborts last | |
199 | * issued command i.e. as ACK for standard PN533. Additionally, | |
200 | * it behaves stange, sending broken or incorrect responses, | |
201 | * when we cancel urb before the chip will send response. | |
202 | */ | |
203 | if (dev->device_type == PN533_DEVICE_ACR122U) | |
204 | return; | |
205 | ||
206 | /* An ack will cancel the last issued command */ | |
207 | pn533_usb_send_ack(dev, flags); | |
208 | ||
209 | /* cancel the urb request */ | |
210 | usb_kill_urb(phy->in_urb); | |
211 | } | |
212 | ||
213 | /* ACR122 specific structs and fucntions */ | |
214 | ||
215 | /* ACS ACR122 pn533 frame definitions */ | |
216 | #define PN533_ACR122_TX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_tx_frame) \ | |
217 | + 2) | |
218 | #define PN533_ACR122_TX_FRAME_TAIL_LEN 0 | |
219 | #define PN533_ACR122_RX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_rx_frame) \ | |
220 | + 2) | |
221 | #define PN533_ACR122_RX_FRAME_TAIL_LEN 2 | |
222 | #define PN533_ACR122_FRAME_MAX_PAYLOAD_LEN PN533_STD_FRAME_MAX_PAYLOAD_LEN | |
223 | ||
224 | /* CCID messages types */ | |
225 | #define PN533_ACR122_PC_TO_RDR_ICCPOWERON 0x62 | |
226 | #define PN533_ACR122_PC_TO_RDR_ESCAPE 0x6B | |
227 | ||
228 | #define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83 | |
229 | ||
230 | ||
231 | struct pn533_acr122_ccid_hdr { | |
232 | u8 type; | |
233 | u32 datalen; | |
234 | u8 slot; | |
235 | u8 seq; | |
236 | ||
237 | /* | |
238 | * 3 msg specific bytes or status, error and 1 specific | |
239 | * byte for reposnse msg | |
240 | */ | |
241 | u8 params[3]; | |
242 | u8 data[]; /* payload */ | |
243 | } __packed; | |
244 | ||
245 | struct pn533_acr122_apdu_hdr { | |
246 | u8 class; | |
247 | u8 ins; | |
248 | u8 p1; | |
249 | u8 p2; | |
250 | } __packed; | |
251 | ||
252 | struct pn533_acr122_tx_frame { | |
253 | struct pn533_acr122_ccid_hdr ccid; | |
254 | struct pn533_acr122_apdu_hdr apdu; | |
255 | u8 datalen; | |
256 | u8 data[]; /* pn533 frame: TFI ... */ | |
257 | } __packed; | |
258 | ||
259 | struct pn533_acr122_rx_frame { | |
260 | struct pn533_acr122_ccid_hdr ccid; | |
261 | u8 data[]; /* pn533 frame : TFI ... */ | |
262 | } __packed; | |
263 | ||
264 | static void pn533_acr122_tx_frame_init(void *_frame, u8 cmd_code) | |
265 | { | |
266 | struct pn533_acr122_tx_frame *frame = _frame; | |
267 | ||
268 | frame->ccid.type = PN533_ACR122_PC_TO_RDR_ESCAPE; | |
269 | /* sizeof(apdu_hdr) + sizeof(datalen) */ | |
270 | frame->ccid.datalen = sizeof(frame->apdu) + 1; | |
271 | frame->ccid.slot = 0; | |
272 | frame->ccid.seq = 0; | |
273 | frame->ccid.params[0] = 0; | |
274 | frame->ccid.params[1] = 0; | |
275 | frame->ccid.params[2] = 0; | |
276 | ||
277 | frame->data[0] = PN533_STD_FRAME_DIR_OUT; | |
278 | frame->data[1] = cmd_code; | |
279 | frame->datalen = 2; /* data[0] + data[1] */ | |
280 | ||
281 | frame->apdu.class = 0xFF; | |
282 | frame->apdu.ins = 0; | |
283 | frame->apdu.p1 = 0; | |
284 | frame->apdu.p2 = 0; | |
285 | } | |
286 | ||
287 | static void pn533_acr122_tx_frame_finish(void *_frame) | |
288 | { | |
289 | struct pn533_acr122_tx_frame *frame = _frame; | |
290 | ||
291 | frame->ccid.datalen += frame->datalen; | |
292 | } | |
293 | ||
294 | static void pn533_acr122_tx_update_payload_len(void *_frame, int len) | |
295 | { | |
296 | struct pn533_acr122_tx_frame *frame = _frame; | |
297 | ||
298 | frame->datalen += len; | |
299 | } | |
300 | ||
301 | static bool pn533_acr122_is_rx_frame_valid(void *_frame, struct pn533 *dev) | |
302 | { | |
303 | struct pn533_acr122_rx_frame *frame = _frame; | |
304 | ||
305 | if (frame->ccid.type != 0x83) | |
306 | return false; | |
307 | ||
308 | if (!frame->ccid.datalen) | |
309 | return false; | |
310 | ||
311 | if (frame->data[frame->ccid.datalen - 2] == 0x63) | |
312 | return false; | |
313 | ||
314 | return true; | |
315 | } | |
316 | ||
317 | static int pn533_acr122_rx_frame_size(void *frame) | |
318 | { | |
319 | struct pn533_acr122_rx_frame *f = frame; | |
320 | ||
321 | /* f->ccid.datalen already includes tail length */ | |
322 | return sizeof(struct pn533_acr122_rx_frame) + f->ccid.datalen; | |
323 | } | |
324 | ||
325 | static u8 pn533_acr122_get_cmd_code(void *frame) | |
326 | { | |
327 | struct pn533_acr122_rx_frame *f = frame; | |
328 | ||
329 | return PN533_FRAME_CMD(f); | |
330 | } | |
331 | ||
332 | static struct pn533_frame_ops pn533_acr122_frame_ops = { | |
333 | .tx_frame_init = pn533_acr122_tx_frame_init, | |
334 | .tx_frame_finish = pn533_acr122_tx_frame_finish, | |
335 | .tx_update_payload_len = pn533_acr122_tx_update_payload_len, | |
336 | .tx_header_len = PN533_ACR122_TX_FRAME_HEADER_LEN, | |
337 | .tx_tail_len = PN533_ACR122_TX_FRAME_TAIL_LEN, | |
338 | ||
339 | .rx_is_frame_valid = pn533_acr122_is_rx_frame_valid, | |
340 | .rx_header_len = PN533_ACR122_RX_FRAME_HEADER_LEN, | |
341 | .rx_tail_len = PN533_ACR122_RX_FRAME_TAIL_LEN, | |
342 | .rx_frame_size = pn533_acr122_rx_frame_size, | |
343 | ||
344 | .max_payload_len = PN533_ACR122_FRAME_MAX_PAYLOAD_LEN, | |
345 | .get_cmd_code = pn533_acr122_get_cmd_code, | |
346 | }; | |
347 | ||
348 | struct pn533_acr122_poweron_rdr_arg { | |
349 | int rc; | |
350 | struct completion done; | |
351 | }; | |
352 | ||
353 | static void pn533_acr122_poweron_rdr_resp(struct urb *urb) | |
354 | { | |
355 | struct pn533_acr122_poweron_rdr_arg *arg = urb->context; | |
356 | ||
357 | dev_dbg(&urb->dev->dev, "%s\n", __func__); | |
358 | ||
359 | print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, | |
360 | urb->transfer_buffer, urb->transfer_buffer_length, | |
361 | false); | |
362 | ||
363 | arg->rc = urb->status; | |
364 | complete(&arg->done); | |
365 | } | |
366 | ||
367 | static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) | |
368 | { | |
369 | /* Power on th reader (CCID cmd) */ | |
370 | u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON, | |
371 | 0, 0, 0, 0, 0, 0, 3, 0, 0}; | |
dbafc289 GKH |
372 | char *buffer; |
373 | int transferred; | |
9815c7cf MT |
374 | int rc; |
375 | void *cntx; | |
376 | struct pn533_acr122_poweron_rdr_arg arg; | |
377 | ||
378 | dev_dbg(&phy->udev->dev, "%s\n", __func__); | |
379 | ||
dbafc289 GKH |
380 | buffer = kmemdup(cmd, sizeof(cmd), GFP_KERNEL); |
381 | if (!buffer) | |
382 | return -ENOMEM; | |
383 | ||
9815c7cf MT |
384 | init_completion(&arg.done); |
385 | cntx = phy->in_urb->context; /* backup context */ | |
386 | ||
387 | phy->in_urb->complete = pn533_acr122_poweron_rdr_resp; | |
388 | phy->in_urb->context = &arg; | |
389 | ||
9815c7cf MT |
390 | print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, |
391 | cmd, sizeof(cmd), false); | |
392 | ||
dbafc289 GKH |
393 | rc = usb_bulk_msg(phy->udev, phy->out_urb->pipe, buffer, sizeof(cmd), |
394 | &transferred, 0); | |
395 | kfree(buffer); | |
396 | if (rc || (transferred != sizeof(cmd))) { | |
9815c7cf MT |
397 | nfc_err(&phy->udev->dev, |
398 | "Reader power on cmd error %d\n", rc); | |
399 | return rc; | |
400 | } | |
401 | ||
402 | rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); | |
403 | if (rc) { | |
404 | nfc_err(&phy->udev->dev, | |
405 | "Can't submit reader poweron cmd response %d\n", rc); | |
406 | return rc; | |
407 | } | |
408 | ||
409 | wait_for_completion(&arg.done); | |
410 | phy->in_urb->context = cntx; /* restore context */ | |
411 | ||
412 | return arg.rc; | |
413 | } | |
414 | ||
415 | static void pn533_send_complete(struct urb *urb) | |
416 | { | |
417 | struct pn533_usb_phy *phy = urb->context; | |
418 | ||
419 | switch (urb->status) { | |
420 | case 0: | |
421 | break; /* success */ | |
422 | case -ECONNRESET: | |
423 | case -ENOENT: | |
424 | dev_dbg(&phy->udev->dev, | |
425 | "The urb has been stopped (status %d)\n", | |
426 | urb->status); | |
427 | break; | |
428 | case -ESHUTDOWN: | |
429 | default: | |
430 | nfc_err(&phy->udev->dev, | |
431 | "Urb failure (status %d)\n", | |
432 | urb->status); | |
433 | } | |
434 | } | |
435 | ||
436 | static struct pn533_phy_ops usb_phy_ops = { | |
437 | .send_frame = pn533_usb_send_frame, | |
438 | .send_ack = pn533_usb_send_ack, | |
439 | .abort_cmd = pn533_usb_abort_cmd, | |
440 | }; | |
441 | ||
442 | static int pn533_usb_probe(struct usb_interface *interface, | |
443 | const struct usb_device_id *id) | |
444 | { | |
445 | struct pn533 *priv; | |
446 | struct pn533_usb_phy *phy; | |
447 | struct usb_host_interface *iface_desc; | |
448 | struct usb_endpoint_descriptor *endpoint; | |
449 | int in_endpoint = 0; | |
450 | int out_endpoint = 0; | |
451 | int rc = -ENOMEM; | |
452 | int i; | |
453 | u32 protocols; | |
454 | enum pn533_protocol_type protocol_type = PN533_PROTO_REQ_ACK_RESP; | |
455 | struct pn533_frame_ops *fops = NULL; | |
456 | unsigned char *in_buf; | |
457 | int in_buf_len = PN533_EXT_FRAME_HEADER_LEN + | |
458 | PN533_STD_FRAME_MAX_PAYLOAD_LEN + | |
459 | PN533_STD_FRAME_TAIL_LEN; | |
460 | ||
461 | phy = devm_kzalloc(&interface->dev, sizeof(*phy), GFP_KERNEL); | |
462 | if (!phy) | |
463 | return -ENOMEM; | |
464 | ||
465 | in_buf = kzalloc(in_buf_len, GFP_KERNEL); | |
6d2f70ca DC |
466 | if (!in_buf) |
467 | return -ENOMEM; | |
9815c7cf MT |
468 | |
469 | phy->udev = usb_get_dev(interface_to_usbdev(interface)); | |
470 | phy->interface = interface; | |
471 | ||
472 | iface_desc = interface->cur_altsetting; | |
473 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | |
474 | endpoint = &iface_desc->endpoint[i].desc; | |
475 | ||
476 | if (!in_endpoint && usb_endpoint_is_bulk_in(endpoint)) | |
477 | in_endpoint = endpoint->bEndpointAddress; | |
478 | ||
479 | if (!out_endpoint && usb_endpoint_is_bulk_out(endpoint)) | |
480 | out_endpoint = endpoint->bEndpointAddress; | |
481 | } | |
482 | ||
483 | if (!in_endpoint || !out_endpoint) { | |
484 | nfc_err(&interface->dev, | |
485 | "Could not find bulk-in or bulk-out endpoint\n"); | |
486 | rc = -ENODEV; | |
487 | goto error; | |
488 | } | |
489 | ||
490 | phy->in_urb = usb_alloc_urb(0, GFP_KERNEL); | |
491 | phy->out_urb = usb_alloc_urb(0, GFP_KERNEL); | |
dbafc289 | 492 | phy->ack_urb = usb_alloc_urb(0, GFP_KERNEL); |
9815c7cf | 493 | |
dbafc289 | 494 | if (!phy->in_urb || !phy->out_urb || !phy->ack_urb) |
9815c7cf MT |
495 | goto error; |
496 | ||
497 | usb_fill_bulk_urb(phy->in_urb, phy->udev, | |
498 | usb_rcvbulkpipe(phy->udev, in_endpoint), | |
499 | in_buf, in_buf_len, NULL, phy); | |
500 | ||
501 | usb_fill_bulk_urb(phy->out_urb, phy->udev, | |
502 | usb_sndbulkpipe(phy->udev, out_endpoint), | |
503 | NULL, 0, pn533_send_complete, phy); | |
dbafc289 GKH |
504 | usb_fill_bulk_urb(phy->ack_urb, phy->udev, |
505 | usb_sndbulkpipe(phy->udev, out_endpoint), | |
506 | NULL, 0, pn533_send_complete, phy); | |
9815c7cf MT |
507 | |
508 | switch (id->driver_info) { | |
509 | case PN533_DEVICE_STD: | |
510 | protocols = PN533_ALL_PROTOCOLS; | |
511 | break; | |
512 | ||
513 | case PN533_DEVICE_PASORI: | |
514 | protocols = PN533_NO_TYPE_B_PROTOCOLS; | |
515 | break; | |
516 | ||
517 | case PN533_DEVICE_ACR122U: | |
518 | protocols = PN533_NO_TYPE_B_PROTOCOLS; | |
519 | fops = &pn533_acr122_frame_ops; | |
520 | protocol_type = PN533_PROTO_REQ_RESP, | |
521 | ||
522 | rc = pn533_acr122_poweron_rdr(phy); | |
523 | if (rc < 0) { | |
524 | nfc_err(&interface->dev, | |
525 | "Couldn't poweron the reader (error %d)\n", rc); | |
526 | goto error; | |
527 | } | |
528 | break; | |
529 | ||
530 | default: | |
531 | nfc_err(&interface->dev, "Unknown device type %lu\n", | |
532 | id->driver_info); | |
533 | rc = -EINVAL; | |
534 | goto error; | |
535 | } | |
536 | ||
537 | priv = pn533_register_device(id->driver_info, protocols, protocol_type, | |
538 | phy, &usb_phy_ops, fops, | |
b16931b1 | 539 | &phy->udev->dev, &interface->dev); |
9815c7cf MT |
540 | |
541 | if (IS_ERR(priv)) { | |
542 | rc = PTR_ERR(priv); | |
543 | goto error; | |
544 | } | |
545 | ||
546 | phy->priv = priv; | |
9815c7cf | 547 | |
32ecc75d AR |
548 | rc = pn533_finalize_setup(priv); |
549 | if (rc) | |
550 | goto error; | |
551 | ||
9815c7cf MT |
552 | usb_set_intfdata(interface, phy); |
553 | ||
554 | return 0; | |
555 | ||
556 | error: | |
557 | usb_free_urb(phy->in_urb); | |
558 | usb_free_urb(phy->out_urb); | |
dbafc289 | 559 | usb_free_urb(phy->ack_urb); |
9815c7cf MT |
560 | usb_put_dev(phy->udev); |
561 | kfree(in_buf); | |
6d2f70ca | 562 | |
9815c7cf MT |
563 | return rc; |
564 | } | |
565 | ||
566 | static void pn533_usb_disconnect(struct usb_interface *interface) | |
567 | { | |
568 | struct pn533_usb_phy *phy = usb_get_intfdata(interface); | |
569 | ||
570 | if (!phy) | |
571 | return; | |
572 | ||
573 | pn533_unregister_device(phy->priv); | |
574 | ||
575 | usb_set_intfdata(interface, NULL); | |
576 | ||
577 | usb_kill_urb(phy->in_urb); | |
578 | usb_kill_urb(phy->out_urb); | |
dbafc289 | 579 | usb_kill_urb(phy->ack_urb); |
9815c7cf MT |
580 | |
581 | kfree(phy->in_urb->transfer_buffer); | |
582 | usb_free_urb(phy->in_urb); | |
583 | usb_free_urb(phy->out_urb); | |
dbafc289 GKH |
584 | usb_free_urb(phy->ack_urb); |
585 | kfree(phy->ack_buffer); | |
9815c7cf MT |
586 | |
587 | nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); | |
588 | } | |
589 | ||
590 | static struct usb_driver pn533_usb_driver = { | |
591 | .name = "pn533_usb", | |
592 | .probe = pn533_usb_probe, | |
593 | .disconnect = pn533_usb_disconnect, | |
594 | .id_table = pn533_usb_table, | |
595 | }; | |
596 | ||
597 | module_usb_driver(pn533_usb_driver); | |
598 | ||
599 | MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>"); | |
600 | MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>"); | |
601 | MODULE_AUTHOR("Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>"); | |
602 | MODULE_DESCRIPTION("PN533 USB driver ver " VERSION); | |
603 | MODULE_VERSION(VERSION); | |
604 | MODULE_LICENSE("GPL"); |