~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/bluetooth/cmtp/capi.c

Version: ~ [ linux-5.8-rc4 ] ~ [ linux-5.7.7 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.50 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.131 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.187 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.229 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.229 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2    CMTP implementation for Linux Bluetooth stack (BlueZ).
  3    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
  4 
  5    This program is free software; you can redistribute it and/or modify
  6    it under the terms of the GNU General Public License version 2 as
  7    published by the Free Software Foundation;
  8 
  9    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 10    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 11    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 12    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
 13    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
 14    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 15    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 16    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 17 
 18    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
 19    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
 20    SOFTWARE IS DISCLAIMED.
 21 */
 22 
 23 #include <linux/export.h>
 24 #include <linux/proc_fs.h>
 25 #include <linux/seq_file.h>
 26 #include <linux/types.h>
 27 #include <linux/errno.h>
 28 #include <linux/kernel.h>
 29 #include <linux/sched/signal.h>
 30 #include <linux/slab.h>
 31 #include <linux/poll.h>
 32 #include <linux/fcntl.h>
 33 #include <linux/skbuff.h>
 34 #include <linux/socket.h>
 35 #include <linux/ioctl.h>
 36 #include <linux/file.h>
 37 #include <linux/wait.h>
 38 #include <linux/kthread.h>
 39 #include <net/sock.h>
 40 
 41 #include <linux/isdn/capilli.h>
 42 #include <linux/isdn/capicmd.h>
 43 #include <linux/isdn/capiutil.h>
 44 
 45 #include "cmtp.h"
 46 
 47 #define CAPI_INTEROPERABILITY           0x20
 48 
 49 #define CAPI_INTEROPERABILITY_REQ       CAPICMD(CAPI_INTEROPERABILITY, CAPI_REQ)
 50 #define CAPI_INTEROPERABILITY_CONF      CAPICMD(CAPI_INTEROPERABILITY, CAPI_CONF)
 51 #define CAPI_INTEROPERABILITY_IND       CAPICMD(CAPI_INTEROPERABILITY, CAPI_IND)
 52 #define CAPI_INTEROPERABILITY_RESP      CAPICMD(CAPI_INTEROPERABILITY, CAPI_RESP)
 53 
 54 #define CAPI_INTEROPERABILITY_REQ_LEN   (CAPI_MSG_BASELEN + 2)
 55 #define CAPI_INTEROPERABILITY_CONF_LEN  (CAPI_MSG_BASELEN + 4)
 56 #define CAPI_INTEROPERABILITY_IND_LEN   (CAPI_MSG_BASELEN + 2)
 57 #define CAPI_INTEROPERABILITY_RESP_LEN  (CAPI_MSG_BASELEN + 2)
 58 
 59 #define CAPI_FUNCTION_REGISTER          0
 60 #define CAPI_FUNCTION_RELEASE           1
 61 #define CAPI_FUNCTION_GET_PROFILE       2
 62 #define CAPI_FUNCTION_GET_MANUFACTURER  3
 63 #define CAPI_FUNCTION_GET_VERSION       4
 64 #define CAPI_FUNCTION_GET_SERIAL_NUMBER 5
 65 #define CAPI_FUNCTION_MANUFACTURER      6
 66 #define CAPI_FUNCTION_LOOPBACK          7
 67 
 68 
 69 #define CMTP_MSGNUM     1
 70 #define CMTP_APPLID     2
 71 #define CMTP_MAPPING    3
 72 
 73 static struct cmtp_application *cmtp_application_add(struct cmtp_session *session, __u16 appl)
 74 {
 75         struct cmtp_application *app = kzalloc(sizeof(*app), GFP_KERNEL);
 76 
 77         BT_DBG("session %p application %p appl %d", session, app, appl);
 78 
 79         if (!app)
 80                 return NULL;
 81 
 82         app->state = BT_OPEN;
 83         app->appl = appl;
 84 
 85         list_add_tail(&app->list, &session->applications);
 86 
 87         return app;
 88 }
 89 
 90 static void cmtp_application_del(struct cmtp_session *session, struct cmtp_application *app)
 91 {
 92         BT_DBG("session %p application %p", session, app);
 93 
 94         if (app) {
 95                 list_del(&app->list);
 96                 kfree(app);
 97         }
 98 }
 99 
100 static struct cmtp_application *cmtp_application_get(struct cmtp_session *session, int pattern, __u16 value)
101 {
102         struct cmtp_application *app;
103 
104         list_for_each_entry(app, &session->applications, list) {
105                 switch (pattern) {
106                 case CMTP_MSGNUM:
107                         if (app->msgnum == value)
108                                 return app;
109                         break;
110                 case CMTP_APPLID:
111                         if (app->appl == value)
112                                 return app;
113                         break;
114                 case CMTP_MAPPING:
115                         if (app->mapping == value)
116                                 return app;
117                         break;
118                 }
119         }
120 
121         return NULL;
122 }
123 
124 static int cmtp_msgnum_get(struct cmtp_session *session)
125 {
126         session->msgnum++;
127 
128         if ((session->msgnum & 0xff) > 200)
129                 session->msgnum = CMTP_INITIAL_MSGNUM + 1;
130 
131         return session->msgnum;
132 }
133 
134 static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
135 {
136         struct cmtp_scb *scb = (void *) skb->cb;
137 
138         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
139 
140         scb->id = -1;
141         scb->data = (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3);
142 
143         skb_queue_tail(&session->transmit, skb);
144 
145         wake_up_interruptible(sk_sleep(session->sock->sk));
146 }
147 
148 static void cmtp_send_interopmsg(struct cmtp_session *session,
149                                         __u8 subcmd, __u16 appl, __u16 msgnum,
150                                         __u16 function, unsigned char *buf, int len)
151 {
152         struct sk_buff *skb;
153         unsigned char *s;
154 
155         BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
156 
157         skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC);
158         if (!skb) {
159                 BT_ERR("Can't allocate memory for interoperability packet");
160                 return;
161         }
162 
163         s = skb_put(skb, CAPI_MSG_BASELEN + 6 + len);
164 
165         capimsg_setu16(s, 0, CAPI_MSG_BASELEN + 6 + len);
166         capimsg_setu16(s, 2, appl);
167         capimsg_setu8 (s, 4, CAPI_INTEROPERABILITY);
168         capimsg_setu8 (s, 5, subcmd);
169         capimsg_setu16(s, 6, msgnum);
170 
171         /* Interoperability selector (Bluetooth Device Management) */
172         capimsg_setu16(s, 8, 0x0001);
173 
174         capimsg_setu8 (s, 10, 3 + len);
175         capimsg_setu16(s, 11, function);
176         capimsg_setu8 (s, 13, len);
177 
178         if (len > 0)
179                 memcpy(s + 14, buf, len);
180 
181         cmtp_send_capimsg(session, skb);
182 }
183 
184 static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *skb)
185 {
186         struct capi_ctr *ctrl = &session->ctrl;
187         struct cmtp_application *application;
188         __u16 appl, msgnum, func, info;
189         __u32 controller;
190 
191         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
192 
193         switch (CAPIMSG_SUBCOMMAND(skb->data)) {
194         case CAPI_CONF:
195                 if (skb->len < CAPI_MSG_BASELEN + 10)
196                         break;
197 
198                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
199                 info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
200 
201                 switch (func) {
202                 case CAPI_FUNCTION_REGISTER:
203                         msgnum = CAPIMSG_MSGID(skb->data);
204 
205                         application = cmtp_application_get(session, CMTP_MSGNUM, msgnum);
206                         if (application) {
207                                 application->state = BT_CONNECTED;
208                                 application->msgnum = 0;
209                                 application->mapping = CAPIMSG_APPID(skb->data);
210                                 wake_up_interruptible(&session->wait);
211                         }
212 
213                         break;
214 
215                 case CAPI_FUNCTION_RELEASE:
216                         appl = CAPIMSG_APPID(skb->data);
217 
218                         application = cmtp_application_get(session, CMTP_MAPPING, appl);
219                         if (application) {
220                                 application->state = BT_CLOSED;
221                                 application->msgnum = 0;
222                                 wake_up_interruptible(&session->wait);
223                         }
224 
225                         break;
226 
227                 case CAPI_FUNCTION_GET_PROFILE:
228                         if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
229                                 break;
230 
231                         controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
232                         msgnum = CAPIMSG_MSGID(skb->data);
233 
234                         if (!info && (msgnum == CMTP_INITIAL_MSGNUM)) {
235                                 session->ncontroller = controller;
236                                 wake_up_interruptible(&session->wait);
237                                 break;
238                         }
239 
240                         if (!info && ctrl) {
241                                 memcpy(&ctrl->profile,
242                                         skb->data + CAPI_MSG_BASELEN + 11,
243                                         sizeof(capi_profile));
244                                 session->state = BT_CONNECTED;
245                                 capi_ctr_ready(ctrl);
246                         }
247 
248                         break;
249 
250                 case CAPI_FUNCTION_GET_MANUFACTURER:
251                         if (skb->len < CAPI_MSG_BASELEN + 15)
252                                 break;
253 
254                         if (!info && ctrl) {
255                                 int len = min_t(uint, CAPI_MANUFACTURER_LEN,
256                                                 skb->data[CAPI_MSG_BASELEN + 14]);
257 
258                                 memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
259                                 strncpy(ctrl->manu,
260                                         skb->data + CAPI_MSG_BASELEN + 15, len);
261                         }
262 
263                         break;
264 
265                 case CAPI_FUNCTION_GET_VERSION:
266                         if (skb->len < CAPI_MSG_BASELEN + 32)
267                                 break;
268 
269                         if (!info && ctrl) {
270                                 ctrl->version.majorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 16);
271                                 ctrl->version.minorversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 20);
272                                 ctrl->version.majormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 24);
273                                 ctrl->version.minormanuversion = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 28);
274                         }
275 
276                         break;
277 
278                 case CAPI_FUNCTION_GET_SERIAL_NUMBER:
279                         if (skb->len < CAPI_MSG_BASELEN + 17)
280                                 break;
281 
282                         if (!info && ctrl) {
283                                 int len = min_t(uint, CAPI_SERIAL_LEN,
284                                                 skb->data[CAPI_MSG_BASELEN + 16]);
285 
286                                 memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
287                                 strncpy(ctrl->serial,
288                                         skb->data + CAPI_MSG_BASELEN + 17, len);
289                         }
290 
291                         break;
292                 }
293 
294                 break;
295 
296         case CAPI_IND:
297                 if (skb->len < CAPI_MSG_BASELEN + 6)
298                         break;
299 
300                 func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
301 
302                 if (func == CAPI_FUNCTION_LOOPBACK) {
303                         int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
304                                                 skb->data[CAPI_MSG_BASELEN + 5]);
305                         appl = CAPIMSG_APPID(skb->data);
306                         msgnum = CAPIMSG_MSGID(skb->data);
307                         cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
308                                                 skb->data + CAPI_MSG_BASELEN + 6, len);
309                 }
310 
311                 break;
312         }
313 
314         kfree_skb(skb);
315 }
316 
317 void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
318 {
319         struct capi_ctr *ctrl = &session->ctrl;
320         struct cmtp_application *application;
321         __u16 appl;
322         __u32 contr;
323 
324         BT_DBG("session %p skb %p len %d", session, skb, skb->len);
325 
326         if (skb->len < CAPI_MSG_BASELEN)
327                 return;
328 
329         if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
330                 cmtp_recv_interopmsg(session, skb);
331                 return;
332         }
333 
334         if (session->flags & BIT(CMTP_LOOPBACK)) {
335                 kfree_skb(skb);
336                 return;
337         }
338 
339         appl = CAPIMSG_APPID(skb->data);
340         contr = CAPIMSG_CONTROL(skb->data);
341 
342         application = cmtp_application_get(session, CMTP_MAPPING, appl);
343         if (application) {
344                 appl = application->appl;
345                 CAPIMSG_SETAPPID(skb->data, appl);
346         } else {
347                 BT_ERR("Can't find application with id %d", appl);
348                 kfree_skb(skb);
349                 return;
350         }
351 
352         if ((contr & 0x7f) == 0x01) {
353                 contr = (contr & 0xffffff80) | session->num;
354                 CAPIMSG_SETCONTROL(skb->data, contr);
355         }
356 
357         capi_ctr_handle_message(ctrl, appl, skb);
358 }
359 
360 static int cmtp_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
361 {
362         BT_DBG("ctrl %p data %p", ctrl, data);
363 
364         return 0;
365 }
366 
367 static void cmtp_reset_ctr(struct capi_ctr *ctrl)
368 {
369         struct cmtp_session *session = ctrl->driverdata;
370 
371         BT_DBG("ctrl %p", ctrl);
372 
373         capi_ctr_down(ctrl);
374 
375         atomic_inc(&session->terminate);
376         wake_up_process(session->task);
377 }
378 
379 static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
380 {
381         DECLARE_WAITQUEUE(wait, current);
382         struct cmtp_session *session = ctrl->driverdata;
383         struct cmtp_application *application;
384         unsigned long timeo = CMTP_INTEROP_TIMEOUT;
385         unsigned char buf[8];
386         int err = 0, nconn, want = rp->level3cnt;
387 
388         BT_DBG("ctrl %p appl %d level3cnt %d datablkcnt %d datablklen %d",
389                 ctrl, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
390 
391         application = cmtp_application_add(session, appl);
392         if (!application) {
393                 BT_ERR("Can't allocate memory for new application");
394                 return;
395         }
396 
397         if (want < 0)
398                 nconn = ctrl->profile.nbchannel * -want;
399         else
400                 nconn = want;
401 
402         if (nconn == 0)
403                 nconn = ctrl->profile.nbchannel;
404 
405         capimsg_setu16(buf, 0, nconn);
406         capimsg_setu16(buf, 2, rp->datablkcnt);
407         capimsg_setu16(buf, 4, rp->datablklen);
408 
409         application->state = BT_CONFIG;
410         application->msgnum = cmtp_msgnum_get(session);
411 
412         cmtp_send_interopmsg(session, CAPI_REQ, 0x0000, application->msgnum,
413                                 CAPI_FUNCTION_REGISTER, buf, 6);
414 
415         add_wait_queue(&session->wait, &wait);
416         while (1) {
417                 set_current_state(TASK_INTERRUPTIBLE);
418 
419                 if (!timeo) {
420                         err = -EAGAIN;
421                         break;
422                 }
423 
424                 if (application->state == BT_CLOSED) {
425                         err = -application->err;
426                         break;
427                 }
428 
429                 if (application->state == BT_CONNECTED)
430                         break;
431 
432                 if (signal_pending(current)) {
433                         err = -EINTR;
434                         break;
435                 }
436 
437                 timeo = schedule_timeout(timeo);
438         }
439         set_current_state(TASK_RUNNING);
440         remove_wait_queue(&session->wait, &wait);
441 
442         if (err) {
443                 cmtp_application_del(session, application);
444                 return;
445         }
446 }
447 
448 static void cmtp_release_appl(struct capi_ctr *ctrl, __u16 appl)
449 {
450         struct cmtp_session *session = ctrl->driverdata;
451         struct cmtp_application *application;
452 
453         BT_DBG("ctrl %p appl %d", ctrl, appl);
454 
455         application = cmtp_application_get(session, CMTP_APPLID, appl);
456         if (!application) {
457                 BT_ERR("Can't find application");
458                 return;
459         }
460 
461         application->msgnum = cmtp_msgnum_get(session);
462 
463         cmtp_send_interopmsg(session, CAPI_REQ, application->mapping, application->msgnum,
464                                 CAPI_FUNCTION_RELEASE, NULL, 0);
465 
466         wait_event_interruptible_timeout(session->wait,
467                         (application->state == BT_CLOSED), CMTP_INTEROP_TIMEOUT);
468 
469         cmtp_application_del(session, application);
470 }
471 
472 static u16 cmtp_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
473 {
474         struct cmtp_session *session = ctrl->driverdata;
475         struct cmtp_application *application;
476         __u16 appl;
477         __u32 contr;
478 
479         BT_DBG("ctrl %p skb %p", ctrl, skb);
480 
481         appl = CAPIMSG_APPID(skb->data);
482         contr = CAPIMSG_CONTROL(skb->data);
483 
484         application = cmtp_application_get(session, CMTP_APPLID, appl);
485         if ((!application) || (application->state != BT_CONNECTED)) {
486                 BT_ERR("Can't find application with id %d", appl);
487                 return CAPI_ILLAPPNR;
488         }
489 
490         CAPIMSG_SETAPPID(skb->data, application->mapping);
491 
492         if ((contr & 0x7f) == session->num) {
493                 contr = (contr & 0xffffff80) | 0x01;
494                 CAPIMSG_SETCONTROL(skb->data, contr);
495         }
496 
497         cmtp_send_capimsg(session, skb);
498 
499         return CAPI_NOERROR;
500 }
501 
502 static char *cmtp_procinfo(struct capi_ctr *ctrl)
503 {
504         return "CAPI Message Transport Protocol";
505 }
506 
507 static int cmtp_proc_show(struct seq_file *m, void *v)
508 {
509         struct capi_ctr *ctrl = m->private;
510         struct cmtp_session *session = ctrl->driverdata;
511         struct cmtp_application *app;
512 
513         seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl));
514         seq_printf(m, "addr %s\n", session->name);
515         seq_printf(m, "ctrl %d\n", session->num);
516 
517         list_for_each_entry(app, &session->applications, list) {
518                 seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping);
519         }
520 
521         return 0;
522 }
523 
524 int cmtp_attach_device(struct cmtp_session *session)
525 {
526         unsigned char buf[4];
527         long ret;
528 
529         BT_DBG("session %p", session);
530 
531         capimsg_setu32(buf, 0, 0);
532 
533         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, CMTP_INITIAL_MSGNUM,
534                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
535 
536         ret = wait_event_interruptible_timeout(session->wait,
537                         session->ncontroller, CMTP_INTEROP_TIMEOUT);
538 
539         BT_INFO("Found %d CAPI controller(s) on device %s", session->ncontroller, session->name);
540 
541         if (!ret)
542                 return -ETIMEDOUT;
543 
544         if (!session->ncontroller)
545                 return -ENODEV;
546 
547         if (session->ncontroller > 1)
548                 BT_INFO("Setting up only CAPI controller 1");
549 
550         session->ctrl.owner      = THIS_MODULE;
551         session->ctrl.driverdata = session;
552         strcpy(session->ctrl.name, session->name);
553 
554         session->ctrl.driver_name   = "cmtp";
555         session->ctrl.load_firmware = cmtp_load_firmware;
556         session->ctrl.reset_ctr     = cmtp_reset_ctr;
557         session->ctrl.register_appl = cmtp_register_appl;
558         session->ctrl.release_appl  = cmtp_release_appl;
559         session->ctrl.send_message  = cmtp_send_message;
560 
561         session->ctrl.procinfo      = cmtp_procinfo;
562         session->ctrl.proc_show     = cmtp_proc_show;
563 
564         if (attach_capi_ctr(&session->ctrl) < 0) {
565                 BT_ERR("Can't attach new controller");
566                 return -EBUSY;
567         }
568 
569         session->num = session->ctrl.cnr;
570 
571         BT_DBG("session %p num %d", session, session->num);
572 
573         capimsg_setu32(buf, 0, 1);
574 
575         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
576                                 CAPI_FUNCTION_GET_MANUFACTURER, buf, 4);
577 
578         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
579                                 CAPI_FUNCTION_GET_VERSION, buf, 4);
580 
581         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
582                                 CAPI_FUNCTION_GET_SERIAL_NUMBER, buf, 4);
583 
584         cmtp_send_interopmsg(session, CAPI_REQ, 0xffff, cmtp_msgnum_get(session),
585                                 CAPI_FUNCTION_GET_PROFILE, buf, 4);
586 
587         return 0;
588 }
589 
590 void cmtp_detach_device(struct cmtp_session *session)
591 {
592         BT_DBG("session %p", session);
593 
594         detach_capi_ctr(&session->ctrl);
595 }
596 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp